多容器应用程序
解释
启动单容器应用程序很容易。例如,执行特定数据处理任务的Python脚本在其所有依赖项与容器内运行。同样,使用小型API端点的静态网站服务的Node.js应用程序可以使用其所有必要的库和依赖项有效地容器化。但是,随着应用程序规模的增长,将它们作为单个容器进行管理变得越来越困难。
想象一下,数据处理Python脚本需要连接到数据库。突然之间,您现在不仅要管理脚本,还要管理同一容器内的数据库服务器。如果脚本需要用户登录,则需要身份验证机制,这将进一步增加容器的大小。
容器的一个最佳实践是每个容器都应该做好一件事并且做好它。虽然此规则有例外,但应避免一个容器执行多项任务的趋势。
现在您可能会问:“我需要分别运行这些容器吗?如果我分别运行它们,我该如何将它们连接在一起?”
虽然`docker run`是启动容器的便捷工具,但使用它来管理不断增长的应用程序堆栈会变得很困难。原因如下:
- 想象一下,运行多个`docker run`命令(前端、后端和数据库),并为开发、测试和生产环境配置不同的配置。这是容易出错且费时的。
- 应用程序经常相互依赖。随着堆栈的扩展,以特定顺序手动启动容器和管理网络连接变得很困难。
- 每个应用程序都需要其`docker run`命令,这使得难以扩展单个服务。扩展整个应用程序意味着可能在不需要提升的组件上浪费资源。
- 持久化每个应用程序的数据需要在每个`docker run`命令中单独挂载卷或配置。这创建了一种分散的数据管理方法。
- 通过单独的`docker run`命令为每个应用程序设置环境变量既繁琐又容易出错。
这就是Docker Compose发挥作用的地方。
Docker Compose 在名为`compose.yml`的单个YAML文件中定义您的整个多容器应用程序。此文件指定所有容器的配置、它们的依赖项、环境变量,甚至卷和网络。使用Docker Compose:
- 您不需要运行多个`docker run`命令。您只需在一个YAML文件中定义您的整个多容器应用程序即可。这集中了配置并简化了管理。
- 您可以按特定顺序运行容器并轻松管理网络连接。
- 您可以简单地向上或向下扩展多容器设置中的单个服务。这允许根据实时需求进行有效的分配。
- 您可以轻松实现持久卷。
- 在Docker Compose文件中轻松设置环境变量。
通过利用Docker Compose运行多容器设置,您可以构建以模块化、可扩展性和一致性为核心的复杂应用程序。
试一试
在本实践指南中,您将首先了解如何使用`docker run`命令基于Node.js、Nginx反向代理和Redis数据库构建和运行计数器Web应用程序。您还将了解如何使用Docker Compose简化整个部署过程。
设置
获取示例应用程序。如果您有Git,您可以克隆示例应用程序的存储库。否则,您可以下载示例应用程序。选择以下选项之一。
在终端中使用以下命令克隆示例应用程序存储库。
$ git clone https://github.com/dockersamples/nginx-node-redis
导航到`nginx-node-redis`目录
$ cd nginx-node-redis
在此目录中,您将找到两个子目录——`nginx`和`web`。
下载源代码并解压。
导航到`nginx-node-redis-main`目录
$ cd nginx-node-redis-main
在此目录中,您将找到两个子目录——`nginx`和`web`。
下载并安装 Docker Desktop。
构建镜像
导航到`nginx`目录,通过运行以下命令构建镜像
$ docker build -t nginx .
导航到`web`目录,并运行以下命令来构建第一个web镜像
$ docker build -t web .
运行容器
在运行多容器应用程序之前,您需要为它们创建网络以便它们都可以通过该网络进行通信。您可以使用`docker network create`命令来执行此操作
$ docker network create sample-app
通过运行以下命令启动Redis容器,这会将它附加到先前创建的网络并创建一个网络别名(对DNS查找很有用)
$ docker run -d --name redis --network sample-app --network-alias redis redis
通过运行以下命令启动第一个web容器
$ docker run -d --name web1 -h web1 --network sample-app --network-alias web1 web
运行以下命令启动第二个web容器
$ docker run -d --name web2 -h web2 --network sample-app --network-alias web2 web
通过运行以下命令启动Nginx容器
$ docker run -d --name nginx --network sample-app -p 80:80 nginx
注意
Nginx通常用作Web应用程序的反向代理,将流量路由到后端服务器。在这种情况下,它会路由到Node.js后端容器(web1或web2)。
通过运行以下命令验证容器是否已启动
$ docker ps
您将看到如下输出
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2cf7c484c144 nginx "/docker-entrypoint.…" 9 seconds ago Up 8 seconds 0.0.0.0:80->80/tcp nginx 7a070c9ffeaa web "docker-entrypoint.s…" 19 seconds ago Up 18 seconds web2 6dc6d4e60aaf web "docker-entrypoint.s…" 34 seconds ago Up 33 seconds web1 008e0ecf4f36 redis "docker-entrypoint.s…" About a minute ago Up About a minute 6379/tcp redis
如果您查看Docker Desktop仪表板,您可以看到容器并更深入地了解其配置。
在一切启动并运行后,您可以打开http://localhost 在您的浏览器中查看站点。刷新页面几次以查看处理请求的主机和请求总数。
web2: Number of visits is: 9 web1: Number of visits is: 10 web2: Number of visits is: 11 web1: Number of visits is: 12
注意
您可能已经注意到,Nginx充当反向代理,可能以轮询方式在两个后端容器之间分配传入请求。这意味着每个请求都可能被定向到不同的容器(web1和web2)进行轮换。输出显示web1和web2容器的连续增量,并且只有在将响应发送回客户端后才会更新存储在Redis中的实际计数器值。
您可以使用Docker Desktop仪表板通过选择容器并选择“删除”按钮来删除容器。
使用Docker Compose简化部署
Docker Compose 提供了一种结构化且简化的方式来管理多容器部署。如前所述,使用 Docker Compose,您无需运行多个docker run
命令。您只需在一个名为compose.yml
的 YAML 文件中定义您的整个多容器应用程序即可。让我们看看它是如何工作的。
导航到项目根目录。在这个目录中,您会找到一个名为compose.yml
的文件。这个 YAML 文件就是所有神奇之处发生的地方。它定义了构成您应用程序的所有服务及其配置。每个服务都指定其镜像、端口、卷、网络以及其功能所需的任何其他设置。
使用
docker compose up
命令启动应用程序。$ docker compose up -d --build
运行此命令时,您应该会看到类似于以下内容的输出。
Running 5/5 ✔ Network nginx-nodejs-redis_default Created 0.0s ✔ Container nginx-nodejs-redis-web1-1 Started 0.1s ✔ Container nginx-nodejs-redis-redis-1 Started 0.1s ✔ Container nginx-nodejs-redis-web2-1 Started 0.1s ✔ Container nginx-nodejs-redis-nginx-1 Started
如果您查看Docker Desktop仪表板,您可以看到容器并更深入地了解其配置。
或者,您可以使用 Docker Desktop Dashboard 通过选择应用程序堆栈并选择**删除**按钮来删除容器。
在本指南中,您学习了与易于出错且难以管理的docker run
相比,使用 Docker Compose 启动和停止多容器应用程序是多么容易。