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

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.shsudo 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:1FROM 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.mzph.cn/news/790694.shtml

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

相关文章

HTML - 你如何使H5页面禁止手动缩放

难度级别:初级及以上 提问概率:40% 我们知道,这道题其实是在考察meta标签的viewport属性,正常情况下设置viewport的代码为 <head><meta name="viewport" content="width=device-width,initial-scale=1.0" …

【MATLAB】PSO_BP神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 1 基本定义 PSO_BP神经网络时序预测算法是一种结合了粒子群优化(PSO)算法和反向传播(BP)神经网络的时序预测方法。它利用了PSO算法的全局搜索能力和BP神经网络的优化能力&#xff0c;能够更准确地预测时序数据。 具体步…

讲讲你对数据结构-线性表了解多少?

线性表 - 数组和矩阵 当谈到线性表时&#xff0c;数组和矩阵是两种常见的数据结构。 数组&#xff08;Array&#xff09;&#xff1a; 数组是有序的元素集合&#xff0c;可以通过索引来访问和操作其中的元素。它是最简单、最基本的数据结构之一。数组的特点包括&#xff1a; …

C++ | Leetcode C++题解之第7题整数反转

题目&#xff1a; 题解&#xff1a; class Solution { public:int reverse(int x) {int rev 0;while (x ! 0) {if (rev < INT_MIN / 10 || rev > INT_MAX / 10) {return 0;}int digit x % 10;x / 10;rev rev * 10 digit;}return rev;} };

wordpress课程项目主题电脑版+手机版自适应

这款主题适合做资源、课程、素材等&#xff0c;演示站&#xff1a;点击查看

八数码问题——A*算法的应用(A-Star)

文章目录 1 问题描述2 启发式搜索3 A*算法3.1 参考网址3.2 是什么3.3 为什么A*算法适用于八数码问题3.4 A* 算法的基本框架 4 A* 算法如何解决八数码问题4.1 八数码状态的存储4.2 启发式函数4.3 构造目标状态元素位置的字典4.4 在二维列表中查找目标元素4.5 A* 算法主体4.6 路径…

RUST语言函数的定义与调用

1.定义函数 定义一个RUST函数使用fn关键字 函数定义语法: fn 函数名(参数名:参数类型,参数名:参数类型) -> 返回类型 { //函数体 } 定义一个没有参数,没有返回类型的参数 fn add() {println!("调用了add函数!"); } 定义有一个参数的函数 fn add(a:u32)…

C++ //练习 11.12 编写程序,读入string和int的序列,将每个string和int存入一个pair中,pair保存在一个vector中。

C Primer&#xff08;第5版&#xff09; 练习 11.12 练习 11.12 编写程序&#xff0c;读入string和int的序列&#xff0c;将每个string和int存入一个pair中&#xff0c;pair保存在一个vector中。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#x…

前端(动态雪景背景+动态蝴蝶)

1.CSS样式 <style>html, body, a, div, span, table, tr, td, strong, ul, ol, li, h1, h2, h3, p, input {font-weight: inherit;font-size: inherit;list-style: none;border-spacing: 0;border: 0;border-collapse: collapse;text-decoration: none;padding: 0;margi…

网站如何运用百度文心一言API进行AI内容创作?

网站如何运用百度文心一言API进行AI内容创作&#xff1f; 当我们做好一个网站的时候会因为创作内容而发愁&#xff0c;随着chatgpt的出现&#xff0c;内容创作已经不再是什么困难的事情&#xff0c;但是由于gpt是国外的&#xff0c;在国内使用有诸多不便&#xff0c;因此我们今…

06-编辑器

gedit编辑器 gedit是Ubuntu系统自带的编辑器&#xff0c;可以用来轻度编辑和记录一些内容。 在终端中我们通过以下命令打开&#xff1a; gedit 要打开或者新建的文件名虽然Ubuntu的图形界面也能通过gedit打开文件&#xff0c;但是用终端打开gedit可以动用更高的权限&#xff…

Apache Pulsar源码解析之Lookup机制

引言 在学习Pulsar一段时间后&#xff0c;相信大家也或多或少听说Lookup这个词&#xff0c;今天就一起来深入剖析下Pulsar是怎么设计的它吧 Lookup是什么 在客户端跟服务端建立TCP连接前有些信息需要提前获取&#xff0c;这个获取方式就是Lookup机制。所获取的信息有以下几种…

Flutter中setState函数的使用注意事项

文章目录 Flutter中setState函数的使用注意事项只能在具有State对象的类中使用不要在build方法中使用将状态更新逻辑放在setState方法内部避免频繁调用使用回调函数更新状态 Flutter中setState函数的使用注意事项 setState()函数是Flutter中非常重要的一个函数&#xff0c;它用…

C#使用Selenium驱动Chrome浏览器

1.Selenium库依赖安装 Selenium WebDriver是Selenium项目的一部分&#xff0c;用于模拟用户在Web应用程序中的交互操作。它支持多种浏览器&#xff0c;如Chrome、Firefox、IE等&#xff0c;且与各种编程语言&#xff08;如Java、Python、C#等&#xff09;兼容&#xff0c;具有…

2012年认证杯SPSSPRO杯数学建模B题(第二阶段)节能减排全过程文档及程序

2012年认证杯SPSSPRO杯数学建模 节能减排、抑制全球气候变暖 B题 白屋顶计划 原题再现&#xff1a; 第二阶段问题   虽然环境学家对地球环境温度的改变有许多种不同观点&#xff0c;但大多数科学家可以达成一个基本的共识&#xff1a;近年来人类的活动&#xff0c;尤指二氧…

云存储中常用的相同子策略的高效、安全的基于属性的访问控制的论文阅读

参考文献为2022年发表的Efficient and Secure Attribute-Based Access Control With Identical Sub-Policies Frequently Used in Cloud Storage 动机 ABE是实现在云存储中一种很好的访问控制手段&#xff0c;但是其本身的计算开销导致在实际场景中应用收到限制。本论文研究了…

ESP32学习---ESP-NOW(一)

ESP32学习---ESP-NOW&#xff08;一&#xff09; 官网简介arduino 官网简介 首先看官网的介绍&#xff1a;https://www.espressif.com.cn/zh-hans/solutions/low-power-solutions/esp-now ESP-NOW 是乐鑫定义的一种无线通信协议&#xff0c;能够在无路由器的情况下直接、快速…

【Java多线程(4)】案例:设计模式

目录 一、什么是设计模式&#xff1f; 二、单例模式 1. 饿汉模式 2. 懒汉模式 懒汉模式-第一次改进 懒汉模式-第二次改进 懒汉模式-第三次改进 一、什么是设计模式&#xff1f; 设计模式是针对软件设计中常见问题的通用解决方案。它们提供了一种被广泛接受的方法来解决…

5米分辨率数字高程模型(DEM)的制作

在现代科技的驱动下&#xff0c;地理信息系统&#xff08;GIS&#xff09;和遥感技术已经取得了惊人的进展。其中一项令人瞩目的技术就是5米分辨率数字高程模型&#xff08;DEM&#xff09;的制作&#xff0c;它是基于多颗高分辨率卫星数据为原始数据&#xff0c;借助智能立体模…

C语言编写Linux的Shell外壳

目录 一、输出命令行 1.1 了解环境变量 1.2 获取用户名、主机名、当前路径 1.3 缓冲区改进MakeCommandLine 二、获取用户命令 2.1 读取函数的选择 2.2 细节优化 2.3 返回值 三、指令和选项分割 3.1 strtok 函数 3.2 分割实现 四、执行命令 4.1 fork 方法 4.2 进…