当前位置: 首页 > news >正文

从入门到深入,Docker新手学习教程

图片

图片

编译整理|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 psdocker 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-appcd ts-express-appnpm init -y
npm install express mongoose dotenvnpm install --save-dev typescript @types/node @types/express @types/mongoose ts-nodetsc --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 imageFROM node:20
# Set the working directory inside the containerWORKDIR /usr/src/app
# Copy package.json and package-lock.jsonCOPY package*.json ./
# Install dependenciesRUN npm install
# Copy the rest of the application codeCOPY . .
# Build the TypeScript codeRUN npm run build
# Expose the port the app runs onEXPOSE 3000
# Command to run the appCMD ["npm", "start"]

6.在项目根目录中创建一个文件:.dockerignore

node_modulesdistnpm-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 logindocker tag ts-express-app your-dockerhub-username/ts-express-app:latestdocker 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.0docker 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-networkdocker network ls

在 Bridge 网络上运行容器 —

docker run -d --name c1 --network my-first-network nginxdocker 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折优惠购票限期发售中!(扫描下方图片二维码了解详情)

图片

相关文章:

从入门到深入,Docker新手学习教程

编译整理&#xff5c;TesterHome社区 作者&#xff5c;Ishaan Gupta 以下为作者观点&#xff1a; Docker 彻底改变了我们开发、交付和运行应用程序的方式。它使开发人员能够将应用程序打包到容器中 - 标准化的可执行组件&#xff0c;将应用程序源代码与在任何环境中运行该代码…...

Postman编写测试脚本

在 Postman 中&#xff0c;编写测试脚本通常使用 JavaScript&#xff0c;这些脚本可以在请求发送前后执行。以下是一些示例代码&#xff0c;展示了如何在 Postman 中使用测试脚本。 1. 测试脚本示例&#xff1a;检查响应状态码 // 测试脚本在请求发送后执行 pm.test("Re…...

代码随想录算法训练Day57|LeetCode200-岛屿数量、LeetCode695-岛屿的最大面积

岛屿数量 题目描述 力扣200-岛屿数量 给你一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 此…...

StopWatch的使用

org.springframework.util.StopWatch 是 Spring 框架提供的一个轻量级的计时工具&#xff0c;用于测量代码执行时间。它比 Apache Commons Lang 的 StopWatch 提供了更多的功能&#xff0c;例如累计多个时间段、打印详细报告等。 以下是如何使用 Spring 的 StopWatch&#xff…...

MySQL基础篇(三)数据库的修改 删除 备份恢复 查看连接情况

对数据库的修改主要指的是修改数据库的字符集&#xff0c;校验规则。 将test1数据库字符集改为gbk。 数据库的删除&#xff1a; 执行完该数据库就不存在了&#xff0c;对应数据库文件夹被删除&#xff0c;级联删除&#xff0c;里面的数据表全部被删除。 注意&#xff1a;不要随…...

android手机电视相框项目-学员做出个bug版本邀请大家review提意见

背景 前几天给我的vip学员布置了一个android手机/电视相框的项目&#xff0c;具体详情看如下链接&#xff1a; https://mp.weixin.qq.com/s/l2roDoco-o59SLlORENZlA 这个项目我说过不给提供答案哈&#xff0c;让各位学员朋友自己独立思考完成哈&#xff0c;因为尽量想让大家慢…...

web零碎知识2

不知道我的这个axios的包导进去没。 找一下关键词&#xff1a; http请求协议&#xff1a;就是进行交互式的格式 需要定义好 这个式一发一收短连接 而且没有记忆 这个分为三个部分 第一个式请求行&#xff0c;第二个就是请求头 第三个就是请求体 以get方式进行请求的失手请求…...

Android项目框架

Android项目基于Android Studio开发&#xff0c;Android Studio使用Gradle作为项目构建工具。新建工程后可以看到如图所示目录结构&#xff0c;将Android切成Project可以看到完整的Android工程目录结构&#xff0c;如图所示。 图1-2 Android项目目录结构 app目录是一个典型的…...

vue 模糊查询加个禁止属性

vue 模糊查询加个禁止属性 父组件通过属性传&#xff0c;是否禁止输入-------默认可以输入...

MySQL 主从复制中 MHA 工具的研究与实践

MySQL 主从复制中 MHA 工具的研究与实践 一、MHA 工具简介二、MHA 的工作原理三、MHA 配置步骤环境准备1. 在主服务器上配置主从复制2. 在从服务器上配置复制 安装 MHA 工具1. 安装必要的依赖包2. 下载并安装 MHA 配置 MHA1. 创建 MHA 配置文件2. 配置 SSH 免密登录 测试 MHA1.…...

Hi3861 OpenHarmony嵌入式应用入门--TCP Server

本篇使用的是lwip编写tcp服务端。需要提前准备好一个PARAM_HOTSPOT_SSID宏定义的热点&#xff0c;并且密码为PARAM_HOTSPOT_PSK LwIP简介 LwIP是什么&#xff1f; A Lightweight TCP/IP stack 一个轻量级的TCP/IP协议栈 详细介绍请参考LwIP项目官网&#xff1a;lwIP - A Li…...

Poker Game, Run Fast

Poker Game, Run Fast 扑克&#xff1a;跑得快 分门别类&#xff1a; 单张从小到大默认 A < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K 跑得快&#xff1a;单张从小到大 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 &…...

订单折扣金额分摊算法|代金券分摊|收银系统|积分分摊|分摊|精度问题|按比例分配|钱分摊|钱分配

一个金额分摊的算法&#xff0c;将折扣分摊按比例&#xff08;细单实收在总体的占比&#xff09;到各个细单中。 此算法需要达到以下要求&#xff1a; 折扣金额接近细单总额&#xff0c;甚至折扣金额等于细单金额&#xff0c;某些时候甚至超过细单总额&#xff0c;要保证实收不…...

Matlab中collectPlaneWave函数的应用

查看文档如下&#xff1a; 可以看出最多5个参数&#xff0c;分别是阵列对象&#xff0c;信号幅度&#xff0c;入射角度&#xff0c;信号频率&#xff0c;光速。 在下面的代码中&#xff0c;我们先创建一个3阵元的阵列&#xff0c;位置为&#xff1a;&#xff08;-1,0,0&#x…...

Linux系统的基础知识和常用命令

1、什么是Linux&#xff1f; 是一种免费使用和自由传播的类UNIX操作系统&#xff0c;其内核由林纳斯本纳第克特托瓦兹于1991年10月5日首次发布&#xff0c;它主要受到Minix和Unix思想的启发&#xff0c;是一个基于POSIX的多用户、多任务、支持多线程和多CPU的操作系统。它能运行…...

三相异步电动机的起动方法

1. 引言 2. 三相笼型异步电动机德起动方法 3. 三相绕线型异步电动机的起动方法 4. 软起动器起动 5. 参考文献 1 引言 三相异步电动机结构简单﹑价格低廉﹑运行可靠﹑维护方便&#xff0c;在工农业生产中得到了广泛应用。为使电动机能够转动起来&#xff0c;并很快达到工作转…...

【LinuxC语言】手撕Http协议之accept_request函数实现(一)

文章目录 前言accept_request函数作用accept_request实现解析方法根据不同方法进行不同操作http服务器响应格式unimplemented函数实现总结前言 在计算机网络中,HTTP协议是一种常见的应用层协议,它定义了客户端和服务器之间如何进行数据交换。在这篇文章中,我们将深入探讨Li…...

Redis Cluster 模式 的具体实施细节是什么样的?

概述 参考&#xff1a;What are Redis Cluster and How to setup Redis Cluster locally ? | by Rajat Pachauri | Medium Redis Cluster 的工作原理是将数据分布在多个节点上&#xff0c;同时确保高可用性和容错能力。以下是 Redis Cluster 运行方式的简要概述&#xff1a; …...

基于大模型的机器人控制

基于大模型的机器人控制是指利用深度学习中的大型神经网络模型来实现对机器人的精确控制。这种方法结合了深度学习的强大表征学习能力和机器人控制的实际需求&#xff0c;旨在提高机器人的自主性、灵活性和智能性。 基本原理 数据收集&#xff1a;首先&#xff0c;需要收集大量…...

在 PostgreSQL 中,如何处理数据的版本控制?

文章目录 一、使用时间戳字段进行版本控制二、使用版本号字段进行版本控制三、使用历史表进行版本控制四、使用 RETURNING 子句获取更新前后的版本五、使用数据库触发器进行版本控制 在 PostgreSQL 中&#xff0c;处理数据的版本控制可以通过多种方式实现&#xff0c;每种方式都…...

Rust 组织管理

Rust 组织管理 Rust 是一种系统编程语言&#xff0c;以其内存安全性、速度和并发性而闻名。它由 Mozilla 开发&#xff0c;并得到了一个庞大而活跃的社区的支持。Rust 的组织管理涉及多个方面&#xff0c;包括项目管理、社区参与、工具和库的维护&#xff0c;以及生态系统的整…...

vb.netcad二开自学笔记1:万里长征第一步Hello CAD!

已入门的朋友请绕行&#xff01; 今天开启自学vb.net 开发autocad&#xff0c;网上相关资料太少了、太老了。花钱买课吧&#xff0c;穷&#xff01;又舍不得&#xff0c;咬牙从小白开始摸索自学吧&#xff0c;虽然注定是踏上了一条艰苦之路&#xff0c;顺便作个自学笔记备忘!积…...

Vue的学习之数据与方法

前段期间&#xff0c;由于入职原因没有学习&#xff0c;现在已经正式入职啦&#xff0c;接下来继续加油学习。 一、数据与方法 文字备注已经在代码中&#xff0c;方便自己学习和理解 <!DOCTYPE html> <html><head><meta charset"utf-8">&l…...

刷题——在二叉树中找到最近公共祖先

在二叉树中找到两个节点的最近公共祖先_牛客题霸_牛客网 int lowestCommonAncestor(TreeNode* root, int o1, int o2) {if(root NULL) return -1;if((root->val o1) || (root->val o2)) return root->val;int left lowestCommonAncestor(root->left, o1, o2);i…...

nginx(三)—从Nginx配置熟悉Nginx功能

一、 Nginx配置文件结构 ... #全局块events { #events块... }http #http块 {... #http全局块server #server块{ ... #server全局块location [PATTERN] #location块{...}location [PATTERN] {...}}server{...}... #http全局块 …...

Python轮子:文件比较器——filecmp

原文链接&#xff1a;http://www.juzicode.com/python-module-filecmp filecmp模块可以用来比较文件或者目录。 安装和导入 filecmp是Python自带的模块&#xff0c;不需要额外安装&#xff0c;直接导入即可&#xff1a; import filecmp as fc #或者 import filecmp cmp()比较…...

uni-app组件 子组件onLoad、onReady事件无效

文章目录 导文解决方法 导文 突然发现在项目中&#xff0c;组件 子组件的onLoad、onReady事件无效 打印也出不来值 怎么处理呢&#xff1f; 解决方法 mounted() {console.log(onLoad, this.dateList);//有效// this.checkinDetails()},onReady() {console.log(onReady, this.da…...

leetcode力扣_排序问题

215.数组中的第K个最大元素 鉴于已经将之前学的排序算法忘得差不多了&#xff0c;只会一个冒泡排序法了&#xff0c;就写了一个冒牌排序法&#xff0c;将给的数组按照降序排列&#xff0c;然后取nums[k-1]就是题目要求的&#xff0c;但是提交之后对于有的示例显示”超出时间限制…...

在 .NET 8 Web API 中实现弹性

在现代 Web 开发中&#xff0c;构建弹性 API 对于确保可靠性和性能至关重要。本文将指导您使用 Microsoft.Extensions.Http.Resilience 库在 .NET 8 Web API 中实现弹性。我们将介绍如何设置重试策略和超时&#xff0c;以使您的 API 更能抵御瞬时故障。 步骤 1.创建一个新的 .…...

linux下高级IO模型

高级IO 1.高级IO模型基本概念1.1 阻塞IO1.2 非阻塞IO1.3 信号驱动IO1.4 IO多路转接1.5 异步IO 2. 模型代码实现2.1 非阻塞IO2.2 多路转接-selectselect函数介绍什么才叫就绪呢&#xff1f;demoselect特点 2.3 多路转接-pollpoll函数介绍poll优缺点demo 2.4 多路转接-epoll&…...

掌握Mojolicious会话管理:构建安全、持久的Web应用

掌握Mojolicious会话管理&#xff1a;构建安全、持久的Web应用 Mojolicious是一个基于Perl的高性能、异步Web开发框架&#xff0c;它提供了一套完整的工具来构建现代Web应用。会话管理是Web开发中的一个关键组成部分&#xff0c;它允许应用识别和保持用户的登录状态。本文将深…...

24西安电子科技大学马克思主义学院—考研录取情况

01、马克思主义学院各个方向 02、24马克思主义学院近三年复试分数线对比 PS&#xff1a;马院24年院线相对于23年院线增加15分&#xff0c;反映了大家对于马克思主义理论学习与研究的热情高涨&#xff0c;也彰显了学院在人才培养、学科建设及学术研究等方面的不断进步与成就。 6…...

12--RabbitMQ消息队列

前言&#xff1a;前面一章内容太多&#xff0c;写了kafka&#xff0c;这里就写一下同类产品rabbitmq&#xff0c;rabbitmq内容较少&#xff0c;正好用来过度一下&#xff0c;概念还是会用一些例子来说明&#xff0c;实际部署的内容会放在概念之后。 1、基础概念 1.1、MQ消息队…...

VMware替换关键技术:核心业务系统中,访存密集型应用的性能优化

越来越多用户采用虚拟化、超融合以及云平台环境来承载其核心业务&#xff0c;核心业务的高并发对性能的要求尤为严格&#xff0c;在VMware替换的热潮下&#xff0c;原VMware用户也更为关注新平台在核心业务上的性能表现是否对标&#xff0c;或实现超越。深信服将通过系列解析&a…...

[单master节点k8s部署]20.监控系统构建(五)Alertmanager

prometheus将监控到的异常事件发送给Alertmanager&#xff0c;然后Alertmanager将报警信息发送到邮箱等设备。可以从下图看出&#xff0c;push alerts是由Prometheus发起的。 安装Alertmanager config文件 [rootmaster prometheus]# cat alertmanager-cm.yaml kind: ConfigMa…...

用MySQL+node+vue做一个学生信息管理系统(四):制作增加、删除、修改的组件和对应的路由

1.下载依赖&#xff1a; npm install vue-router 在src目录下新建一个文件夹router&#xff0c;在router文件夹下新建一个文件router.js文件,在component目录下新建增加删除和修改的组件&#xff0c;引入router.js当中 此时的init组件为主页面&#xff08;&#xff08;二、三&…...

磁盘就是一个超大的Byte数组,操作系统是如何管理的?

磁盘在操作系统的维度看&#xff0c;就是一个“超大的Byte数组”。 那么操作系统是如何对这块“超大的Byte数组”做管理的呢&#xff1f; 我们知道在逻辑上&#xff0c;上帝说是用“文件”的概念来进行管理的。于是&#xff0c;便有了“文件系统”。那么&#xff0c;文件系统…...

14-28 剑和诗人2 - 高性能编程Bend和Mojo

介绍&#xff1a; 在不断发展的计算世界中&#xff0c;软件和硬件之间的界限变得越来越模糊。随着我们不断突破技术可能性的界限&#xff0c;对能够利用现代硬件功能的高效、可扩展的编程语言的需求从未如此迫切。 Bend和 Mojo是编程语言领域的两种新秀&#xff0c;它们有望弥…...

Stable Diffusion:最全详细图解

Stable Diffusion&#xff0c;作为一种革命性的图像生成模型&#xff0c;自发布以来便因其卓越的生成质量和高效的计算性能而受到广泛关注。不同于以往的生成模型&#xff0c;Stable Diffusion在生成图像的过程中&#xff0c;采用了独特的扩散过程&#xff0c;结合深度学习技术…...

Apache Seata分布式事务之Seata-Client原理及流程详解

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 前言 在分布式系统中&#xff0c;分布式事务是一个必须要解决的问题&#xff0c;目前使用较多…...

Linux wget报未找到命令

wget报未找到命令需要安装wget 1、下载wget安装文件&#xff0c;本次于华为云资源镜像下载 地址&#xff1a;https://mirrors.huaweicloud.com/centos-vault/7.8.2003/os/x86_64/Packages/ 2、下载后上传到安装服务器/install_package&#xff0c;执行命令安装 rpm -ivh /i…...

38条Web测试经验分享

1. 页面链接检查 每一个链接是否都有对应的页面&#xff0c;并且页面之间切换正确。可以使用一些工具&#xff0c;如LinkBotPro、File-AIDCS、HTML Link Validater、Xenu等工具。 LinkBotPro不支持中文&#xff0c;中文字符显示为乱码&#xff1b;HTML Link Validater只能测…...

TCP报文校验和(checksum)计算

一. 原理 将TCP相关内容&#xff08;TCP伪头部TCP头部TCP内容&#xff09;转换成16比特的字符&#xff0c;然后进行累加&#xff0c;最后结果进行取反。TCP伪头部是固定的&#xff0c;下文有相关代码展示。 二. 源码 源码 #include <stdio.h> #include <stdlib.h&…...

【ue5】虚幻5同时开多个项目

正常开ue5项目我是直接在桌面点击快捷方式进入 只会打开一个项目 如果再想打开一个项目需要进入epic 再点击启动就可以再开一个项目了...

【Python实战因果推断】23_倾向分3

目录 Propensity Score Matching Inverse Propensity Weighting Propensity Score Matching 另一种控制倾向得分的常用方法是匹配估计法。这种方法搜索具有相似可观测特征的单位对&#xff0c;并比较接受干预与未接受干预的单位的结果。如果您有数据科学背景&#xff0c;您可…...

Qt源码解析之QObject

省去大部分virtual和public方法后&#xff0c;Qobject主要剩下以下成员&#xff1a; //qobject.h class Q_CORE_EXPORT Qobject{Q_OBJECTQ_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)Q_DECLARE_PRIVATE(QObject) public:Q_I…...

【算法专题】模拟算法题

模拟算法题往往不涉及复杂的数据结构或算法&#xff0c;而是侧重于对特定情景的代码实现&#xff0c;关键在于理解题目所描述的情境&#xff0c;并能够将其转化为代码逻辑。所以我们在处理这种类型的题目时&#xff0c;最好要现在演草纸上把情况理清楚&#xff0c;再动手编写代…...

分库分表真的适合你的系统吗?

曾几何时&#xff0c;“并发高就分库&#xff0c;数据大就分表”已经成了处理 MySQL 数据增长问题的圣经。 面试官喜欢问&#xff0c;博主喜欢写&#xff0c;候选人也喜欢背&#xff0c;似乎已经形成了一个闭环。 但你有没有思考过&#xff0c;分库分表真的适合你的系统吗&am…...

9 redis,memcached,nginx网络组件

课程目标: 1.网络模块要处理哪些事情 2.reactor是怎么处理这些事情的 3.reactor怎么封装 4.网络模块与业务逻辑的关系 5.怎么优化reactor? io函数 函数调用 都有两个作用:io检测 是否就绪 io操作 1. int clientfd = accept(listenfd, &addr, &len); 检测 全连接队列…...

【MySQL】事务四大特性以及实现原理

事务四大特性 原子性&#xff08;Atomicity&#xff09; 事务中的所有操作要么全部完成&#xff0c;要么全部不执行。如果事务中的任何一步失败&#xff0c;整个事务都会被回滚&#xff0c;以保持数据的完整性。 一致性&#xff08;Consistency&#xff09; 事务应确保数据库…...