怎么快速上手虚拟化(容器)技术——以 Docker 为例

news2024/11/29 2:50:43

Docker 整体介绍

Docker 是一种使用 Go 语言开发的容器工具。所谓容器,实际上是一种虚拟化技术,用于为应用提供虚拟化的运行环境,相较于虚拟机具有轻量级、低延迟的特性。

下面是对上述介绍的说明:

应用程序运行需要一定的依赖支持,即所谓运行环境.在软件的开发、测试和发布等过程中,必然面临环境迁移问题————需要多次应对环境变化问题。重复构建环境既不经济、也不高效、甚至可能对开发团队心理健康造成负面影响。

通常的解决方案是“将环境打包”,即将软件和运行环境一起交付给用户(下一阶段开发人员)。虚拟机毕竟是整个系统镜像,除了依赖还由过多不必要的东西,而且虚拟机这种在 Host OS 上运行 Guest OS 的形式相对笨重。容器技术则在这两方面表现更优。

总而言之,借助 Docker,可以像管理应用程序一样管理硬件,而且相对于虚拟机占用的资源少得多。

With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code, you can significantly reduce the delay between writing code and running it in production.

Docker 架构介绍

类似于调试工具 GDB,Docker 也采用 Client-Server 架构,即用户使用 Docker Client 通过 SOKCET 等网络接口与作为 Server 的 Docker Daemon 交互。Docker Daemon 既可以部署在本地,也可以部署在远程服务器上,也就是说下图中的 Host 既可以是 127.0.0.1,也可以是某个服务器(使用远端的开发环境)。

在这里插入图片描述

下面将阐释图中的 Images、Containers 和 Registry 等概念的内涵。

Docker Daemon 和 Docker Client

Dokcer 的 Server 端,负责实际响应 Client 的请求,完成 镜像(Image)、容器(Container)等对象的管理。

Doker Daemon 支持与其他 Docker Daemon 通信。

Docker Registry

用于存储 Docker Image。Docker 还提供类似于镜像商店的平台 Docker Hub,公开发布 Docker Image。Docker 支持自建 Registry,使用类似于 Git,通过PUSH 和 PULL 命令发布和获取 Registry 中的 Docker Image。

Image 和 Continer

所谓 Docker 镜像,即打包好的环境。Docker Image 是只读的,Docker Daemon 可以根据 Docker Image 构建出 Docker Container。

Image 和 Continer 的关系,可以描述为

A container is a runnable instance of an image.

即 Container 是可运行的实例化 Image。说起来有点绕口,借用面向对象的概念,可以把二者的关系理解成:Class 和 Object 的关系。Image 有点像设计图,Docker 可用一个 Image 构建多个 Container 实例,即多个一模一样的、相互独立的环境。

实操1:镜像制作与容器化

准备工作

  1. 安装 Docker Desktop:https://docs.docker.com/get-docker/
  2. 安装 Git Client:https://git-scm.com/downloads
  3. 安装 VS Code https://code.visualstudio.com/

其实就是安装 Docker、Git 和 选择合适的编辑器。Git 和 文本编辑器大概都已经安装了,这里提一下 Docker 的安装。

建议使用官方脚本而不是按照上面链接的 Docker Desktop 安装教程进行安装。

只需要两个命令————用 Curl 获取安装脚本 test-docker.sh 和运行脚本:

 curl -fsSL https://test.docker.com -o test-docker.sh
 sudo sh test-docker.sh

安装过程输出如下:

在这里插入图片描述

获取实例源码

Docker 提供了学习用的软件源码,可以下载下来用于后续的实验。获取命令如下:

git clone https://github.com/docker/getting-started-app.git

源码目录结构如下:

├── getting-started-app/
│ ├── package.json
│ ├── README.md
│ ├── spec/
│ ├── src/
│ └── yarn.lock

制作镜像(Image)

  1. 进入源码目录 getting-started-app

  2. 创建 Docker 镜像制作脚本 Dockerfile(功能类似于 Makefile,说明制作镜像的参数)。Dockerfile 的内容改成:

# syntax=docker/dockerfile:1

FROM node:18-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]
EXPOSE 3000

大概意思是基于 node:18-alpine 这个镜像构建。

  1. 开始构建,用 -t 指定镜像的名字,最后是 Dockerfile 所在目录的相对路径
$> docker build -t getting-started .

可能出现如下问题:
在这里插入图片描述
这是因为没有安装 cmdtests,可以通过下面的命令安装:

$> sudo apt-get insall cmdtest
  1. 运行镜像,构建成运行应用的容器:
$> sudo docker run -dp 127.0.0.1:3000:3000 getting-started 

上述命令表示运行镜像 getting-started, 将容器的端口 3000 映射到主机的 127.0.0.1 地址的 3000 端口上。其中 -d 参数表示在后台运行容器,-p 参数用于指定端口映射。run 的镜像名要和前面 build-t 指定的一致。

  1. 验证容器构建结果。getting-started-app 是一个使用 js 编写的前端工程,功能是在页面上创建和删除信息栏。

完成第 4 步后等十几秒钟,通过浏览器访问地址 ‘127.0.0.1:3000’, 可以看到如下页面:

在这里插入图片描述

容器间数据共享

容器内程序对文件的创建/更新都是在容器自有的文件系统镜像上进行的,单个容器运行时的文件操作对其它容器不可见。要实现文件操作的一致性,则需要借助 Volume

Volume 可以把容器某个文件路径挂载(mount)到主机(host)上,使容器内的更改也能在主机上看到。如果在容器重启的时候挂载同一个目录,那就能实现容器之间的文件共享。

更具象地说,现在这个应用程序 getting-started-app 把所有数据都存在同一个文件(一个 SQLite 数据库文件)里。只要在主机上保存这个文件,就能够共享给其它容器。

综上所述,我们需要一个 Volume,用于把容器中的应用程序的数据保存在主机上,以便共享给其他容器。

创建 Volume。

使用 volaume create 命令创建一个 Volume

$> docker volume create todo-db

移除所有 getting-started-app 容器

  1. 用 docker ps 命令查看运行中的容器:

  2. 移除所有 getting-started-app 容器。上图只有一个,CONTINER ID 是 7b53603df907, 则使用命令 sudo docker rm -f 7b53603df907 移除这个容器。

启动镜像同时挂载 Volume

$> docker run -dp 127.0.0.1:3000:3000 --mount type=volume,src=todo-db,target=/etc/todos getting-started

和前面相比,这里多了一个 --mount 参数,type 是 volume, src 要和前面使用 volaume create 命令创建的 Volume 保持一致。

测试挂载 Volume 的效果

  1. 打开页面 127.0.0.1:3000,输入框中输入任意字符后点击 Add Item,在页面上创建新的 Item,然后移除 getting-started-app 这个容器。

  2. 再次以挂载 Volume 的方式启动容器(注意要挂载同一个 Volume)。刷新刚才打开的页面,发现和移除容器前一致(刚才创建的 Item 没有因为重新启动容器而消失)。

Docker 容器间实时数据共享(bind mounts)

虽然 Volume 能够实现数据共享,但对容器中的应用和主机而言,这种共享更像是容器有一个 Write Back 策略的缓存,主机并不能实时收到应用对共享数据的修改,主机上对应用程序源码的修改也不能实时传递给容器。

Docker 提供的 bind mounts 方法用来解决上述问题。 通过 bind mount 把源码文挂载到容器上,每次保存文件都会立即把修改传递给容器。这样我们就能一边运行着容器调试源码了。

use a bind mount to mount source code into the container. The container sees the changes you make to the code immediately, as soon as you save a file.

当然,有人认为把开发工具放到容器里也行,但那样容器就过于臃肿了,失去了原本的轻薄特质。

bind mounts 命令格式

 $> docker run -dp 127.0.0.1:3000:3000 \
    -w /app --mount type=bind,src="$(pwd)",target=/app \
    node:18-alpine \
    sh -c "yarn install && yarn run dev"
  • -w 指定命令的当前路径/工作路径
  • –mount type=bind,src=" ( p w d ) " , t a r g e t = / a p p :把 ‘ (pwd)",target=/app:把 ` (pwd)",target=/app:把PWD挂载到容器的/app` 目录下。注意这个路径必须是绝对路径形式,不然会遇到如下报错:

在这里插入图片描述

用下列命令把 /home/hhy/ws/getting-stared-app 挂载到容器的 /app 目录下:

 $> sudo docker run -dp 127.0.0.1:3000:3000 \
    -w /app --mount type=bind,src="/home/hhy/ws/getting-stared-app",target=/app \
    node:18-alpine \
    sh -c "yarn install && yarn run dev"

然后用下列命令查看 Docker 的 log(先用 docker ps 命令查看容器 ID, 这里演示的容器 ID 是 0x0a9c4c9d22 ):

$> sudo docker -f 0a9c4c9d22

上述命令运行结果如下:

在这里插入图片描述

测试 bind mounts 效果

  1. 浏览器打开页面 127.0.0.1:3000
  2. 修改主机上当前目录下的 src/static/js/app.js,把 109 行的 Add Item 修改成 Item,这对应页面上按钮的提示文字。
  3. 保存修改后刷新页面,发现按钮上的提示文字变成 Item, 同步成功。

容器间通信

创建通信网络

容器间的通信时借助 Network 实现的,这也是一种 Docker 对象。要使用 Network,首先需要创建一个对象:

$> docker network create todo-app

上述命令创建了一个名为 todo-app 的 Network

启动数据库(单独一个容器,连接到通信网络)

然后启动一个 Mysql 的容器 mysql:8.0

$> docker run -d \
    --network todo-app --network-alias mysql \
    -v todo-mysql-data:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=secret \
    -e MYSQL_DATABASE=todos \
    mysql:8.0

本地没有这个镜像,Docker 会自动从 Registry 下载,启动过程如下:
在这里插入图片描述

运行 getting-started-app

使用如下命令启动我们前面多次用到的运行 getting-started-app 容器,将其连接到和数据库容器共享的 Network todos。

$> docker run -dp 127.0.0.1:3000:3000 \
  -w /app -v "$(pwd):/app" \
  --network todo-app \
  -e MYSQL_HOST=mysql \
  -e MYSQL_USER=root \
  -e MYSQL_PASSWORD=secret \
  -e MYSQL_DB=todos \
  node:18-alpine \
  sh -c "yarn install && yarn run dev"

使用 sudo docker ps 查看容器列表,可以看到两个容器,一个是运行 getting-startted-app 的容器,另一个是数据库容器。

在这里插入图片描述

创建新数据(修改页面)

浏览器打开 http://127.0.0.1:3000, 添加几个信息栏,如下:

在这里插入图片描述

验证数据库

使用如下命令打开 mysql 数据库:

$> docker exec -it <mysql-container-id> mysql -p todos

然后用命令 select * from todos_items 在数据库中搜索 todos_items.

上述两条命令运行结果如下(注意 Enter password 后面输入启动数据库容器时的设置 -e MYSQL_ROOT_PASSWORD=secret):

在这里插入图片描述

Docker 自动化部署

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1559925.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

qtcreator的信号槽链接

在ui文件中简单创建一个信号槽连接并保存可以在ui_mainwindow.h下 class Ui_MainWindow 类 void setupUi(QMainWindow *MainWindow)函数 找到对应代码 QObject::connect(pushButton, SIGNAL(clicked()), MainWindow, SLOT(close())); 下拉&#xff0c;由于 class MainWind…

@Transactional使用细节

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 动态代理回顾 Spring的声明式事务管理是建立在 AOP 的基础之上的。Spring AOP是通过动态代理实现的。如果代理对象实现了接口&#xff0c;则使用JDK的动态代理&#xff1b;…

SpringBoot整合knife4J 3.0.3

Knife4j的前身是swagger-bootstrap-ui,前身swagger-bootstrap-ui是一个纯swagger-ui的ui皮肤项目。项目正式更名为knife4j,取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍,更名也是希望把她做成一个为Swagger接口文档服务的通用性解决方案,不仅仅只是专注于前端Ui…

【IP组播】PIM-SM的RP、RPF校验

目录 一&#xff1a;PIM-SM的RP 原理概述 实验目的 实验内容 实验拓扑 1.基本配置 2.配置IGP 3.配置PIM-SM和静态RP 4.配置动态RP 5.配置Anycast RP 二&#xff1a; RPF校验 原理概述 实验目的 实验内容 实验拓扑 1.基本配置 2.配置IGP 3.配置PIM-DM 4.RPF校…

LeetCode_876(链表的中间结点)

//双指针//时间复杂度O(n) 空间复杂度O(1)public ListNode middleNode(ListNode head) {ListNode slowhead,fast head;while (fast!null && fast.next!null){slow slow.next;fast fast.next.next;}return slow;} 1->2->3->4->5->null 快指针移动两个…

如何创建一个TCP多人聊天室?

一、什么是TCP&#xff1f; TCP&#xff08;Transmission Control Protocol&#xff09;是一种可靠的 面向连接的协议 &#xff0c;可以保证数据在传输过程中不会丢失、重复或乱序。 利用TCP实现简单聊天程序&#xff0c;需要客户端和服务器端之间建立TCP连接&#xff0c;并通…

一条SQL在MySQL中的执行过程

图解&#xff1a; 第⼀步&#xff1a;连接器 过程 1. 建⽴连接&#xff1a;与客户端进⾏ TCP 三次握⼿建⽴连接&#xff1b; 2. 校验密码&#xff1a;校验客户端的⽤户名和密码&#xff0c;如果⽤户名或密码不对&#xff0c;则会报错&#xff1b;3. 权限判断&#xff1a…

HCIP【GRE VPN配置】

目录 实验要求&#xff1a; 实验配置思路&#xff1a; 实验配置过程&#xff1a; 一、按照图式配置所有设备的IP地址 &#xff08;1&#xff09;首先配置每个接口的IP地址 &#xff08;2&#xff09;配置静态路由使公网可通 二、在公网的基础上创建GRE VPN隧道&#xff0…

【yy讲解PostCSS是如何安装和使用】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

保研线性代数机器学习基础复习2

1.什么是群&#xff08;Group&#xff09;&#xff1f; 对于一个集合 G 以及集合上的操作 &#xff0c;如果G G-> G&#xff0c;那么称&#xff08;G&#xff0c;&#xff09;为一个群&#xff0c;并且满足如下性质&#xff1a; 封闭性&#xff1a;结合性&#xff1a;中性…

Linux多进程通信(1)——无名管道及有名管道使用例程

管道是半双工通信&#xff0c;如果需要 双向通信&#xff0c;则需要建立两个管道&#xff0c; 无名管道&#xff1a;只能父子进程间通信&#xff0c;且是非永久性管道通信结构&#xff0c;当它访问的进程全部终止时&#xff0c;管道也随之被撤销 有名管道&#xff1a;进程间不需…

【核弹级软安全事件】XZ Utils库中发现秘密后门,影响主要Linux发行版,软件供应链安全大事件

Red Hat 发布了一份“紧急安全警报”&#xff0c;警告称两款流行的数据压缩库XZ Utils&#xff08;先前称为LZMA Utils&#xff09;的两个版本已被植入恶意代码后门&#xff0c;这些代码旨在允许未授权的远程访问。 此次软件供应链攻击被追踪为CVE-2024-3094&#xff0c;其CVS…

从大厂裸辞半年,我靠它成功赚到了第一桶金,如果你失业了,建议这样做,不然时间太久了就完了

程序员接私活和创业是许多技术从业者关注的话题。下面我将介绍一些程序员接私活和创业的渠道和建议&#xff1a; 接私活的渠道&#xff1a; 自媒体平台&#xff1a; 可以利用社交媒体、个人博客、技术社区等平台展示自己的作品和技能&#xff0c;吸引潜在客户。自由工作平台&…

C#(winform) 调用MATLAB函数

测试环境 VisualStudio2022 / .NET Framework 4.7.2 Matlab2021b 参考&#xff1a;C# Matlab 相互调用 Matlab 1、编写Matlab函数 可以没有任何参数单纯定义matlab处理的函数&#xff0c;输出的数据都存在TXT中用以后期读取数据 function [result,m,n] TEST(list) % 计算…

数据分析之Tebleau 的度量名称和度量值

度量名称 包含所有的维度 度量值 包含所有的度量 度量名称包含上面所有的维度&#xff0c;度量值包含上面所有的度量 当同时创建两个或两个以上度量或维度时&#xff0c;会自动创建度量名称和度量值 拖入省份为行(这会是还没有值的) 可以直接将销售金额拖到数值这里 或者将销售…

Kafka 学习之:基于 flask 框架通过具体案例详解生产消费者模型,这一篇文章就够了

文章目录 案例信息介绍后端异步处理请求和后端同步处理请求同步方式异步方式 环境文件目录配置.envrequirements.txt 完整代码ext.pyapp.pykafka_create_user.py 运行方式本地安装 kafka运行 app.py使用 postman 测试建立 http 长连接&#xff0c;等待后端处理结果发送 RAW DAT…

# 达梦数据库知识点

达梦数据库知识点 测试数据 -- SYSDBA.TABLE_CLASS_TEST definitionCREATE TABLE SYSDBA.TABLE_CLASS_TEST (ID VARCHAR(100) NOT NULL,NAME VARCHAR(100) NULL,CODE VARCHAR(100) NULL,TITLE VARCHAR(100) NULL,CREATETIME TIMESTAMP NULL,COLUMN1 VARCHAR(100) NULL,COLUMN…

ARP原理

解析原理 动态ARP通过广播ARP请求和单播ARP应答这两个过程完成地址解析 当需要通信的两台主机处于同一网段时&#xff0c;如上图中的Host_1和Host_3&#xff0c;Host_1要向Host_3发送数据。 首先&#xff0c;Host_1会查找自己本地缓存的ARP表&#xff0c;确定是否包含Host_3对…

精通Go语言文件上传:深入探讨r.FormFile函数的应用与优化

1. 介绍 1.1 概述 在 Web 开发中&#xff0c;文件上传是一项常见的功能需求&#xff0c;用于允许用户向服务器提交文件&#xff0c;如图像、文档、视频等。Go 语言作为一门强大的服务器端编程语言&#xff0c;提供了方便且高效的方式来处理文件上传操作。其中&#xff0c;r.F…

155 Linux C++ 通讯架构实战10,工具telent 和 wireshark的使用

telnet工具使用介绍 windows 上开启telnet linux 上开始telnet 使用telnet //是一款命令行方式运行的客户端TCP通讯工具&#xff0c;可以连接到服务器端&#xff0c;往服务器端发送数据&#xff0c;也可以接收从服务器端发送过来的信息&#xff1b; //类似nginx5_1_1_clie…