编译整理|TesterHome社区
作者|Ishaan Gupta
以下为作者观点:
Docker 彻底改变了我们开发、交付和运行应用程序的方式。它使开发人员能够将应用程序打包到容器中 - 标准化的可执行组件,将应用程序源代码与在任何环境中运行该代码所需的操作系统 (OS) 库和依赖项相结合。本文将介绍 docker 的关键概念、安装、命令、构建映像、管理容器、网络、数据持久性以及其他一些高级主题。
那么,让我们开始吧。但在学习 docker 之前,你需要先了解容器/容器化。(本文内容较长,请耐心阅读!)
容器和容器化
什么是容器?
容器是轻量级、独立且可执行的软件包,其中包含运行软件所需的一切,包括代码、运行时、系统工具、库和设置。容器将软件与其环境隔离开来,并确保其能够统一运行,尽管开发和暂存之间存在差异。这意味着它们允许将应用程序及其所有依赖项和库打包成一个单元,该单元可以在任何具有容器运行时(例如 Docker)的机器上运行。
什么是容器化?
容器化是将软件代码及其依赖项打包的过程,以便它可以在任何基础架构上统一一致地运行。此方法可确保应用程序在从一个计算环境移动到另一个计算环境时可以轻松部署并可靠运行。
容器化的好处
-
一致性:无论应用程序在何处运行,其行为都相同。
-
效率:容器是轻量级的,共享主机操作系统内核,比虚拟机使用更少的系统资源。
-
可扩展性:随着应用程序规模逐渐增长,可以轻松地扩大或缩小应用程序的规模。
-
隔离性:每个容器都在其隔离的环境中运行,提高了安全性和稳定性。
什么是 Docker?
Docker 是一个开源平台,可让开发人员轻松高效地构建、部署、运行、更新和管理容器化应用程序。以下是 Docker 受欢迎的一些主要原因:
Docker 简化了开发工作流程,减少了“它在我的计算机上运行”的问题,并允许高效部署和扩展应用程序。
Docker 的主要优点:
-
可移植性:无论应用程序部署在何处,其运行方式都相同。
-
可扩展性:根据需求轻松地扩大或缩小应用程序的规模。
-
隔离性:容器封装应用程序及其依赖项,确保它们彼此独立运行。
Docker 的历史
Docker于2013 年 3 月由 DotCloud(现为 Docker, Inc.)首次发布。Docker 的理念是创建一种轻量级、可移植且高效的方式,用于在不同环境中一致地打包和运行应用程序。这受到了集装箱运输概念的启发,在集装箱运输概念中,应用程序及其依赖项被打包到可以轻松移动和部署的标准化容器中。
如今,Docker 已在各行各业得到广泛采用,并得到了庞大而活跃的开发者和贡献者社区的支持。它已成为容器化的基础技术,并引发了其他相关技术的发展,例如用于容器编排的 Kubernetes。
Docker入门
在深入了解 Docker 之前,需要在系统上安装它。Docker 适用于多个平台,包括 Windows、macOS 和 Linux。
安装 Docker
按照官方网站上适合的操作系统的说明进行操作。https://docs.docker.com/get-docker/
安装后,验证 Docker 是否正在运行:
docker — version
Docker 架构
了解Docker的架构:
Docker 组件
Docker 使用客户端-服务器架构,包含几个关键组件:
1.Docker 客户端:允许用户与 Docker 交互的命令行界面 (CLI) 工具。它与 Docker 守护程序通信以执行命令。
2.Docker Daemon(或 Docker Engine):Docker Engine 是一种开源容器化技术,允许开发人员将应用程序打包到容器中。容器是标准化的可执行组件,结合了应用程序源代码与在任何环境中运行该代码所需的操作系统 (OS) 库和依赖项。它监听 Docker API 请求并相应地处理它们。
3.containerd:管理容器生命周期的核心组件,包括启动、停止和管理容器进程。
4.runc:一个轻量级的 CLI 工具,用于根据开放容器计划 (OCI) 规范创建和运行容器。
5.Docker Registry:存储和分发 Docker 镜像的服务。Docker Hub 是默认的公共注册表,但也可以使用私有注册表。它类似于 GitHub,但它允许您推送镜像而不是源代码。
6.Docker 网络:为容器提供网络功能,使它们能够相互通信并与外界通信。
7.Docker Volumes 和 Bind Mounts:实现容器和主机系统之间的数据持久性和共享。
8.Docker Compose一种使用 YAML 文件定义和运行多容器应用程序的工具。
Docker 如何运行应用程序
1.构建:Docker 客户端向 Docker 守护进程发送构建请求,Docker 守护进程根据 中的指令创建镜像Dockerfile。
2.运送:图像存储在 Docker 注册表(公共或私有)中,可以从那里下载和共享。
3.运行:Docker 客户端请求 Docker 守护进程根据镜像创建并运行容器。
Docker 镜像
Docker 镜像是一个轻量级、独立的可执行包,其中包含运行软件所需的一切,包括代码、运行时、库、环境变量和配置文件。
拉取 Docker 镜像
你可以从 Docker Hub 中提取镜像:
docker pull hello-world
拉取镜像后,可以使用 docker run 命令轻松运行镜像。
docker 镜像和容器之间的区别可以形象地想象,容器就是你从 github 获取的一些源代码在你的机器上运行 node app.js,而镜像是 github 上的代码库。
基本docker命令
1.检查Docker 版本
docker version
2.查看系统范围的 Docker 信息
docker info
3.列出所有 Docker 镜像
docker images
4.列出正在运行的容器
docker ps
docker ps -a // List All Containers (Running and Stopped)
5.从注册表中提取镜像
docker pull node:20 // Here 20 specifies a specific version of the node we want to pull
6.从映像创建并启动新容器
在下面的例子中,我们以分离模式(-d)部署 NGINX 服务器,将主机端口 8080 映射到容器端口 80。
docker run -d -p 8080:80 nginx
7.停止正在运行的容器并将其删除
docker stop <container_id>
docker rm <container_id> // Remove a Stopped Container
8.删除图像
docker rmi <image_id>
9.构建Docker 映像
docker build -t <your-image-name> .
10.)将镜像推送至注册表
docker push <Name of the image> <Name of the repo>
Docker 端口映射说明
Docker 中的端口映射是将主机上的端口映射到容器中的端口的过程。这对于从 Docker 主机外部访问容器内运行的应用程序至关重要。
端口映射的工作原理
假设有一个在端口 3000 上的 Docker 容器内运行的 Web 服务器。默认情况下,此端口只能在 Docker 网络内访问,而不能从主机或外部网络访问。
为了使该服务器在容器外部可访问,需要将端口从主机转发到容器。
例子:
docker run -p [HOST_PORT]:[CONTAINER_PORT] [IMAGE-NAME]
-p是用于指定端口映射的标志。
Dockerfile
Dockerfile 是一个文本文件,其中包含一系列关于如何构建 Docker 镜像的指令。每条指令都会在镜像中创建一个层,并且这些层会被缓存以加快未来的构建速度。
Dockerfile 中的关键指令:
-
FROM:设置后续指令的基础映像。
-
WORKDIR:设置容器内的工作目录。
-
COPY:将文件从主机系统复制到容器。
-
RUN:在容器中执行命令。
-
CMD:指定容器启动时运行的命令。
-
EXPOSE:记录容器监听的端口。
.dockerignore
.dockerignore 文件的工作方式类似于.gitignore 文件。它指定在构建 Docker 镜像时应忽略哪些文件和目录。这有助于保持镜像的轻量级,避免不必要的文件。这会减少构建上下文的大小,并提高构建时间。添加 node_modules、dist 文件夹等等。
如何构建 docker 镜像?
我们将以将基本的 mongo-express typescript 应用程序 docker 化为例。
1.初始化项目
mkdir ts-express-app
cd ts-express-app
npm init -y
npm install express mongoose dotenv
npm install --save-dev typescript @types/node @types/express @types/mongoose ts-node
tsc --init
2.创建 tsconfig.json
{
“compilerOptions” :{
“target” :“ES6” ,
“module” :“commonjs” ,
“outDir” :“。/dist” ,
“rootDir” :“。/src” ,
“strict” :true
}
}
3.创建 src/index.ts
import express from 'express';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
const PORT = 3000;
const DB_URL = process.env.DATABASE_URL || '';
mongoose.connect(DB_URL, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB', err));
app.get('/', (req, res) => {
res.send('Ram Ram bhai Sareya Ne');
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
4.创建 package.json 文件和 .env 文件
"scripts": {
"start": "node dist/index.js",
"build": "tsc"
}
DATABASE_URL=mongodb://localhost:27017/ts-express-app
5.在项目根目录中创建Dockerfile
# Use the Node.js 20 image as the base image
FROM node:20
# Set the working directory inside the container
WORKDIR /usr/src/app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the TypeScript code
RUN npm run build
# Expose the port the app runs on
EXPOSE 3000
# Command to run the app
CMD ["npm", "start"]
6.在项目根目录中创建一个文件:.dockerignore
node_modules
dist
npm-debug.log
7.)构建Docker 映像
docker build -t ts-express-app .
上述命令应该可以成功运行并给出类似如下的输出:
8.)运行Docker容器
构建映像后,可以使用以下命令从中运行容器:
docker run -p 3000:3000 ts-express-app
就像我之前说的,上面的代码运行了你的容器,并将主机上的端口 3000 映射到容器的端口 3000。你可以访问 localhost:3000 并看到容器成功运行。
在上图中,可以看到我的图像列在 docker images 中,我可以看到容器在端口 3000 上运行,该端口与机器端口 3000 映射。花点时间在这里玩一玩,分析一下这里发生了什么。此外,在上面的命令中,我使用了一些我之前没有解释过的额外的东西。找出并了解它是你的家庭作业。如果你找到了它,请在评论部分对其进行评论,并对其进行适当的解释 :)
现在,你可以使用 3 个简单命令将镜像推送到 docker hub 注册表 -
9.将镜像推送到Docker Registry
docker login
docker tag ts-express-app your-dockerhub-username/ts-express-app:latest
docker push your-dockerhub-username/ts-express-app:latest
在上方输入您的 dockerhub 用户名,代替“your-dockerhub-username”。我使用了表达式标签,稍后我会解释,现在请耐心等待!
恭喜你将第一个镜像推送到 dockerhub。现在我相信您已经熟悉了构建镜像和运行容器的基础知识,让我们更深入地了解一下。
现在在生产模式下,你可以隐藏 .env 文件以保护您的机密。那么如何在不使用 .env 文件的情况下将这些 .env 中的机密告知 docker 呢?
只需使用“-e”标志即可将环境变量发送到您的应用程序。
docker run -p 3000:3000 -e DATABASE_URL=mongodb://localhost:27017/ts-express-app ts-express-app
Docker Tags(标签)
Docker 标签传达有关特定镜像版本/变体的有用信息。标签允许你从 Docker 注册表中识别和提取镜像的不同版本。它们是镜像 ID 的别名,通常如下所示:f1477ec11d12。这只是一种引用镜像的方式。一个很好的例子是 Git 标签如何引用你历史记录中的特定提交。
标记 Docker 镜像的一般语法是:
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
如果没有指定标签,Dockerlatest默认使用该标签。
标签使用的两种最常见情况是:
1.在构建镜像时,我们使用以下命令:
docker build -t username/image_name:tag_name .
2. 通过命令明确标记图像tag。
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
3.版本管理:标签通常用于指示镜像的不同版本。例如,您可能有1.0、1.1、2.0等标签,表示主要或次要版本更新。
4.环境或阶段标识:标签可以帮助区分开发、暂存和生产环境。例如,您可能有dev、staging和等标签prod。
5.架构或平台识别:标签可以识别为不同架构或平台构建的图像,例如amd64、arm64或windows。
让我们通过在命令中使用标签来进一步理解它-
1.使用标签构建 Docker 映像:
docker build -t express-mongo-app:1.0 .
2.拉取特定标签:
docker pull node:14.18.0
3.使用新标签标记现有图像:
docker tag express-mongo-app:1.0 express-mongo-app:latest
4.使用标签管理版本:
使用语义版本控制(MAJOR.MINOR.PATCH)—
docker build -t express-mongo-app:1.0.0 .
docker tag express-mongo-app:1.0.0 express-mongo-app:1.0
docker tag express-mongo-app:1.0.0 express-mongo-app:latest
Docker exec 命令
该docker exec命令允许你在正在运行的 Docker 容器内运行命令。这对于调试、运行管理任务、创建文件夹/卷或检查容器的状态非常有用。
基本docker exec用法
docker exec [OPTIONS] CONTAINER_ID|CONTAINER_NAME COMMAND [ARG…]
-
选项:各种选项,如-it交互模式。
-
CONTAINER:容器的名称或 ID。
-
COMMAND:您想要在容器内运行的命令。
-
[ARG…]:命令的参数。
这将在正在运行的容器内打开一个交互式 Bash shell。然后你可以在容器环境中运行命令、检查文件、创建/删除卷或执行脚本。
选项-it代表docker exec“-interactive -tty”,它允许您与容器的shell进行交互。
现在你可能想知道我上面提到的卷是什么。让我们深入探讨一下!
Docker Volumes
Docker Volumes 是挂载在 Docker 容器上的文件系统,用于保存容器生成的数据。
什么是 Docker 文件系统?
Docker 容器执行 Docker 镜像中指定的软件堆栈。镜像由在 Union File System 上运行的只读层组成。当我们启动新容器时,Docker 会在镜像层之上添加一个读写层,使容器能够像传统的 Linux 文件系统一样运行。因此,容器内的每个文件修改都会在读写层中生成一个可运行的副本。但是,当容器停止或删除时,读写层就会消失。
Docker 管理保存在主机文件系统某个部分(Linux 上为 /var/lib/docker/volumes)中的卷。文件系统的这一部分不应由非 Docker 进程更改。在 Docker 中,卷是存储数据的最有效方式。使用 docker volume create 命令,我们可以直接创建卷,或者 Docker 在创建容器或服务时可以为我们创建卷。
主要有三种类型的卷:
-
Named Volumes:由 Docker 管理并存储在主机文件系统上的某个位置。
-
Bind Mounts:将目录或文件从主机挂载到容器中。在主机系统上,绑定挂载可以保存在任何地方。这些可能是关键的系统文件夹或文件。它们始终可由在 Docker 主机或 Docker 容器中运行的非 Docker 进程修改。相比之下,绑定挂载不如卷有用。
-
tmpfs Mounts:将临时文件系统挂载到容器中,存储在主机的内存中。这些挂载永远不会写入主机系统的文件系统;相反,它们仅保存在主机系统的内存中。无论是在 Docker 主机上还是在容器中,它都不会存储在磁盘上。敏感或非持久状态数据可以在容器的持续时间内存储在 tmpfs 挂载上。
命名卷:
使用以下命令创建命名卷:
docker volume create my-ts-app-data
现在,让我们将卷挂载到容器内的目录中。我们正在将卷挂载my-ts-app-data到/app/data容器内的目录中。写入/app/data容器内的任何数据都将存储在主机上的命名卷中。
docker run -d -p 3000:3000 -e DATABASE_URL=mongodb://mongo:27017/ts-express-app -v my-ts-app-data:/data/db ts-express-app
使用docker volume inspect “my-ts-app-data”命令显示有关卷的详细信息,包括其在主机文件系统上的位置。
要删除不再需要的卷,只需使用“rm”命令。
docker volume rm my-ts-app-data
Docker 中卷的工作
现在,让我们尝试一些新东西。假设我想在 mongoDB 指南针应用中可视化我的数据。但是我如何将它连接到容器中的卷?
通过运行以下命令在本地启动 mongo 容器 -
docker run -p 27017:27017 -d mongo
打开你的mongoDB指南针并连接到27017端口。创建一个数据库和集合并在其中插入一些数据并保存。
添加了一个新的数据库和一些随机数据
现在终止容器,然后重新启动它。打开 mongoDB 指南针并检查我们之前创建的数据库和数据。你看到了什么?它不见了,对吧。
那么我们如何保存数据?你猜对了。使用卷!
我们之前已经创建了一个名为“my-ts-app-data”的卷,我们只使用它。将卷挂载到 mongo 容器的/data/db目录中,然后使用以下命令运行它。
docker run -d -v my-ts-app-data:/data/db -p 27017:27017 mongo
现在重复上述步骤,创建一个数据库并在其中添加数据。关闭容器,重新启动它并重新检查您之前输入的数据。您将看到您的数据已持久保存!
现在,既然我们已经了解了命名卷,现在让我们深入研究一些核心 docker 主题。正如您在上面注意到的,我在解释 docker 卷时使用了“层”这个词。但什么是层?让我们看看……
Docker 中的层(Layers In Docker)
到目前为止,我们知道 Docker 构建由一系列有序的构建指令组成。Dockerfile 中的每个指令大致转换为一个层,也称为镜像层。当您从镜像创建新容器时,会在镜像层顶部添加一个新的可写层,从而允许容器进行更改而无需修改底层镜像层。
什么是 Docker 层?
1.基础层:这是 Docker 镜像的起点。它包含操作系统,例如 Ubuntu、Alpine 等等(无论您的 dockerfile 指定什么)。此层是不可变的,并作为后续层的基础。
2.中间层:这些层代表 Dockerfile 中的指令,例如RUN、COPY和ADD。每条指令都会在前一条指令之上创建一个新层。中间层是只读且缓存的。
3.顶部读/写层:当您从镜像运行容器时,Docker 会在只读镜像层之上添加一个可写层。这允许容器进行更改而无需修改底层镜像。
4.可重复使用和可共享:层可缓存并可在不同的镜像之间重复使用,从而提高镜像的构建和共享效率。如果多个镜像是从同一个基础镜像构建的,或者共享通用指令,则它们可以重复使用相同的层,从而减少存储空间并加快镜像下载和构建速度。
如何创建图层
层是根据 Dockerfile 中指定的指令创建的。Dockerfile 中的每个指令都会在先前的层之上生成一个新层。以下是 Dockerfile 示例:
FROM ubuntu: 18.04 // This instruction creates a base layer by pulling the ubuntu: 18.04 image from the Docker registry.
COPY . /app // This instruction creates a new layer on top of the base layer. It copies the entire contents of the build context (the directory containing the Dockerfile) into the /app directory inside the container.
RUN make /app // This instruction creates another layer by running the make /app command inside the container. This command builds the application located in the /app directory.
CMD python /app/app.py // This creates a new layer and specifies the default command to run when the container starts, which is python /app/app.py.
在上图中我们可以看到,每条指令都会在之前的指令之上创建一个新层,形成一个层堆栈,构成最终的 Docker 镜像。为了更加直观,您可以参考下图来了解这里到底发生了什么。
图层的图像表示
层缓存(Layer Caching)
当我们使用 Dockerfile 构建 Docker 镜像时,Docker 会按顺序处理每条指令并为每个指令创建一个新层。如果镜像的某个层未更改,则 Docker 构建器会从构建缓存中获取该层。如果某个层自上次构建以来发生了变化,则必须重建该层及其后面的所有层。让我用一个例子来解释一下——
首次构建图像
对 app.js 文件进行微小修改,第二次构建图像
正如你在上面的屏幕截图中看到的,在第一张图片中,我已经将我的 express 应用程序构建为一个图像,我们可以看到每个层都是从头开始构建的。现在我做了一个小改动(只是console.log('hi')在 app.js 文件中添加了一个,现在我正在重建图像。所以现在在第二张图片中你可以看到第 2、3、4 层被缓存,因为它们没有变化,但是由于文件发生了变化,docker 确认了该变化,因此第 5 层没有被缓存并从头开始构建。并且由于第 5 层已更改,因此在其上构建的所有层(在其之后)都将从头开始重建。
注意:尽管截图中仍未显示缓存,但图 2 中的第 1 层仍处于缓存状态。我其实不知道为什么,如果您发现了,请在评论中告诉我。不过不用担心,它确实被缓存了。
现在,你已经对将应用程序 docker 化以及其内部工作原理以及 docker 中的层有了很好的了解。现在,在继续前进之前,请稍事休息,摆弄卷,创建它们并在软件中访问它们。还可以通过构建和重建它们,使用多个基于技术堆栈的应用程序来玩转您的 dockerfile。尝试优化 dockerfile 以减少步骤/层,并最大限度地利用缓存层来提高效率。
Docker 网络
默认情况下,Docker 容器无法相互通信。因此,docker 网络允许容器相互通信并与外界通信。它们支持隔离、安全性以及对 Docker 容器之间通信的控制。
Docker 网络的类型
Docker 提供了几种类型的网络:
1.桥接网络:
独立容器的默认网络类型。桥接网络在主机和容器之间创建基于软件的桥梁。连接到网络的容器可以相互通信,但它们与网络外部的容器隔离。网络中的每个容器都分配有自己的 IP 地址。由于网络桥接到主机,因此容器也能够在 LAN 和互联网上通信。但它们不会作为物理设备出现在 LAN 上。
2.主机网络:
使用主机网络模式的容器共享主机的网络堆栈,没有任何隔离。它们没有分配自己的 IP 地址,端口绑定将直接发布到主机的网络接口。这意味着侦听端口 80 的容器进程将绑定到<your_host_ip>:80
3.覆盖网络:
覆盖网络是跨多个 Docker 主机的分布式网络。该网络允许任何主机上运行的所有容器相互通信,而无需操作系统级路由支持。覆盖网络实现了 Docker Swarm 集群的网络,但当您运行两个单独的 Docker Engine 实例且容器必须直接相互联系时,您也可以使用它们。这允许您构建自己的类似 Swarm 的环境。
4.Macvlan网络:
Macvlan 是另一个高级选项,它允许容器作为物理设备出现在您的网络上。它的工作原理是为网络中的每个容器分配一个唯一的 MAC 地址。此网络类型要求您将主机的一个物理接口专用于虚拟网络。还必须适当配置更广泛的网络,以支持运行许多容器的活动 Docker 主机可能创建的大量 MAC 地址。
5.ipvlan:
IPvLAN 是一种驱动程序,可精确控制分配给容器的 IPv4 和 IPv6 地址,以及第 2 层和第 3 层 VLAN 标记和路由。当您将容器化服务与现有物理网络集成时,此驱动程序非常有用。IPvLAN 网络分配有自己的接口,与基于桥接的网络相比,它具有性能优势。
6. 无网络:
隔离的、没有网络接口的容器。
让我们尝试让容器互相对话。
使用以下命令创建网络(默认情况下它是桥接网络):—
当您运行一个容器而没有指定网络时,它将连接到桥接网络。
docker network create my-first-network
docker network ls
在 Bridge 网络上运行容器 —
docker run -d --name c1 --network my-first-network nginx
docker run -d --name c2 --network my-first-network nginx
现在让我们将容器 1 连接到容器 2,我们将进入 c1,然后 ping c2
docker exec -it c1 /bin/bash
ping c2
你可以看到它正在运行。现在让我们尝试一些新东西。我将在一个容器中运行 mongo,在另一个容器中运行我的 express 应用程序,然后尝试通过我的 express 应用程序访问 mongo 容器。使用我们之前创建的相同的 express 应用程序代码,只需在下面的 .env 文件中即可 ——
DATABASE_URL=[container_name]://mongodb:27017/ts-express-app-dbDATABASE_URL=mongodb://mongodb:27017/ts-express-app-db
docker run -d --name mongodb --network my-first-network -v my-ts-app-data:/data/db -p 27017:27017 mongodocker run -d -p 3000:3000 --network my-first-network -e DATABASE_URL='mongodb://mongodb:27017/ts-express-app-db' ts-express-appYou can see both container up, now try adding some data using postman or curl command in your terminal. You will see a success response, to confirm that the data is in mongodb, you can go inside the container and run below mongo commands.
docker exec -it mongodb mongo use mydatabase db.users.find().pretty()
你还可以检查 mongoDB 的容器日志来确认数据是否存储。
删除网络——
docker network rm my-first-network
# remove all unused network (networks that aren't connected to even a single container)
docker network prune
断开容器与网络的连接——
docker network disconnect my-first-network mongodb
Docker 组成
Docker Compose 是一款可用于定义和运行多容器 Docker 应用程序的工具。它使用 YAML 文件 ( docker-compose.yml) 来配置和编排组成应用程序的服务,包括它们的依赖项、网络、卷和其他配置设置。
到目前为止,我们一直在使用的 Express 应用程序的docker-compose.yml文件示例:
version: '3.9'
services:
ts-express-app:
build: .
image: "express-mongo-ts-docker"
container_name: ts-express-app
ports:
- "3000:3000"
environment:
- MONGO_URL=mongodb://mongodb:27017/ts-express-app-db
depends_on:
- mongodb
mongodb:
image: mongo
container_name: mongodb
volumes:
- my-ts-app-data:/data/db
ports:
- "27017:27017"
volumes:
my-ts-app-data:
让我们逐行解释一下上述文件的含义——
1.版本声明:
version: '3.9':指定Docker Compose文件格式的版本。
2.服务:
服务是部署单元,用于定义要使用哪个容器镜像。我在上面的文件中定义了 2 个服务
a.) ts-express-app
这项服务定义了我们的 Express 应用程序。
-
build: 从当前目录中的 Dockerfile 构建 Docker 镜像。
-
image: "express-mongo-ts-docker":将图像命名为express-mongo-ts-docker。(可选添加)
-
container_name: ts-express-app:设置容器名称为ts-express-app。
-
ports: - "3000:3000":端口映射照常,无需解释。
-
environment: - MONGO_URL=mongodb://mongodb:27017/ts-express-app-dbMONGO_URL:设置我们的应用用于连接 MongoDB 的环境变量。此 URL 指向mongodb下面 Compose 文件中定义的服务。
-
depends_on: - mongodb:确保ts-express-app服务在服务后启动mongodb。
B)mongodb:
该服务定义 MongoDB 数据库。
-
image: mongo:使用来自 Docker Hub 的官方 MongoDB 镜像。
-
container_name: mongodb:设置容器名称为mongodb。
-
volumes: - my-ts-app-data:/data/db:将 Docker 卷挂载my-ts-app-data到/data/db容器中,这是 MongoDB 存储数据的地方。(同样,我们之前已经学过这一点,因此需要深入解释)
-
ports: - "27017:27017":端口映射照常(再次无需解释……呼……)
3.卷Volumes
my-ts-app-data:我们在文件末尾定义了我们在这里使用的卷。
好的,既然我们已经学会了编写文件,请复制上述代码并docker-compose.yml在应用程序的根目录中定义一个文件。然后进入终端并运行命令docker-compose up --build,等待它构建您的图像并启动容器。您将看到成功消息,现在您的 mongo 和 express 应用程序容器终于在同一个网络上运行,并正确连接到我们定义的卷,可供使用。
要停止应用程序,请使用命令 -docker-compose down
下面是我们的 docker 仪表板的图片,可以在其中看到一个 docker 容器在我们正在运行的两个容器中运行(我们的 mongo 和 express 应用程序)。在第三张图片中,我使用 POSTMAN 添加了一些数据,然后使用 GET req 从我们的数据库中检索了数据。
很简单,不是吗!:)
此外,我们还可以定义如下所示的自定义网络和一些其他自定义的自解释内容。如果我们没有像上面那样定义网络,docker 将自动为我们的服务创建一个默认网络。此默认网络通常以我们的 docker-compose.yml 文件所在的项目目录命名。
我还在下面附加了我们的 express 应用程序的 github 存储库链接,只需克隆、安装库、按照文件中的定义创建卷docker-compose.yml并运行docker-compose up --build命令即可。
是的,就是这样。这就是你的docker-compose主要目标!剩下的就等你去探索了!
在 docker 中还有很多更高级的东西需要学习,但本文就讲到这里。我很快就会写这篇文章的第二部分,其中一部分是关于 kubernetes 的。到那时,我们就可以练习今天学到的东西了。
最后的想法
在本文中,我通过示例介绍了 docker 的几乎所有基本概念。我尝试解释初学者需要了解的所有内容,我可以自信地说,你已经为 docker 做好准备了!
我希望你理解并能理解其中的大部分内容,我知道这篇文章可能会很长,但请相信我,我试图总结初学者开始使用 docker 所需的一切。像往常一样,遇到麻烦或想自己尝试使用 docker 的新事物时,请务必阅读官方文档(https://docs.docker.com/guides/)的具体内容。(原文链接:https://levelup.gitconnected.com/docker-beginner-to-expert-tutorial-68555aa3e544)
由TesterHome社区主办的MTSC2024第十三届中国互联网测试开发大会,将于2024年7月20日在上海举行。
大会日程:主会场+5个平行专场(LLM测试创新、质量保障、效能提升、游戏、智能终端质效),详情:MTSC2024上海大会主会场、五大专场→议题亮点
8折优惠购票限期发售中!(扫描下方图片二维码了解详情)