Docker Compose 快速入门
本教程旨在通过指导您完成基本 Python Web 应用程序的开发,介绍 Docker Compose 的基本概念。
该应用程序使用 Flask 框架,在 Redis 中包含一个点击计数器,提供了一个关于如何在 Web 开发场景中应用 Docker Compose 的实际示例。
即使您不熟悉 Python,这里演示的概念也应该易于理解。
这是一个非规范性的示例,仅突出显示了 Compose 的关键功能。
先决条件
确保您已
- 安装了最新版本的 Docker Compose
- 基本了解 Docker 概念以及 Docker 的工作原理
步骤 1:设置
为项目创建一个目录
$ mkdir composetest $ cd composetest
在您的项目目录中创建一个名为
app.py
的文件,并将以下代码粘贴到其中import time import redis from flask import Flask app = Flask(__name__) cache = redis.Redis(host='redis', port=6379) def get_hit_count(): retries = 5 while True: try: return cache.incr('hits') except redis.exceptions.ConnectionError as exc: if retries == 0: raise exc retries -= 1 time.sleep(0.5) @app.route('/') def hello(): count = get_hit_count() return 'Hello World! I have been seen {} times.\n'.format(count)
在本示例中,
redis
是应用程序网络上 redis 容器的主机名,并使用默认端口6379
。注意
请注意
get_hit_count
函数的编写方式。这个基本的重试循环会在 Redis 服务不可用时尝试多次请求。这在启动时非常有用,因为应用程序会上线,但如果 Redis 服务需要在应用程序生命周期内的任何时间重新启动,它也会使应用程序更具弹性。在集群中,这也有助于处理节点之间短暂的连接中断。在您的项目目录中创建另一个名为
requirements.txt
的文件,并将以下代码粘贴到其中flask redis
创建一个
Dockerfile
并粘贴以下代码# syntax=docker/dockerfile:1 FROM python:3.10-alpine WORKDIR /code ENV FLASK_APP=app.py ENV FLASK_RUN_HOST=0.0.0.0 RUN apk add --no-cache gcc musl-dev linux-headers COPY requirements.txt requirements.txt RUN pip install -r requirements.txt EXPOSE 5000 COPY . . CMD ["flask", "run", "--debug"]
这告诉 Docker
- 从 Python 3.10 镜像开始构建镜像。
- 将工作目录设置为
/code
。 - 设置
flask
命令使用的环境变量。 - 安装 gcc 和其他依赖项
- 复制
requirements.txt
并安装 Python 依赖项。 - 向镜像添加元数据,以描述容器正在侦听端口 5000
- 将项目中的当前目录
.
复制到镜像中的工作目录.
中。 - 将容器的默认命令设置为
flask run --debug
。
重要
检查
Dockerfile
是否没有文件扩展名,例如.txt
。某些编辑器可能会自动附加此文件扩展名,这会导致在您运行应用程序时出现错误。有关如何编写 Dockerfile 的更多信息,请参阅 Dockerfile 参考。
步骤 2:在 Compose 文件中定义服务
Compose 简化了对整个应用程序堆栈的控制,使您可以轻松地在单个、易于理解的 YAML 配置文件中管理服务、网络和卷。
在您的项目目录中创建一个名为 compose.yaml
的文件,并将以下内容粘贴到其中
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
此 Compose 文件定义了两个服务:web
和 redis
。
web
服务使用一个从当前目录的 Dockerfile
构建的镜像。然后,它将容器和主机绑定到公开的端口 8000
。此示例服务使用 Flask Web 服务器的默认端口 5000
。
redis
服务使用从 Docker Hub 注册表中拉取的公共 Redis 镜像。
有关 compose.yaml
文件的更多信息,请参阅 Compose 的工作原理。
步骤 3:使用 Compose 构建和运行应用程序
只需一个命令,您就可以从配置文件中创建和启动所有服务。
从项目目录中,运行
docker compose up
启动应用程序。$ docker compose up Creating network "composetest_default" with the default driver Creating composetest_web_1 ... Creating composetest_redis_1 ... Creating composetest_web_1 Creating composetest_redis_1 ... done Attaching to composetest_web_1, composetest_redis_1 web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) redis_1 | 1:C 17 Aug 22:11:10.480 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo redis_1 | 1:C 17 Aug 22:11:10.480 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1, just started redis_1 | 1:C 17 Aug 22:11:10.480 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf web_1 | * Restarting with stat redis_1 | 1:M 17 Aug 22:11:10.483 * Running mode=standalone, port=6379. redis_1 | 1:M 17 Aug 22:11:10.483 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128. web_1 | * Debugger is active! redis_1 | 1:M 17 Aug 22:11:10.483 # Server initialized redis_1 | 1:M 17 Aug 22:11:10.483 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled. web_1 | * Debugger PIN: 330-787-903 redis_1 | 1:M 17 Aug 22:11:10.483 * Ready to accept connections
Compose 会拉取 Redis 镜像,为您的代码构建镜像,并启动您定义的服务。在本例中,代码在构建时会静态地复制到镜像中。
在浏览器中输入
http://localhost:8000/
即可查看正在运行的应用程序。如果无法解析,您也可以尝试
http://127.0.0.1:8000
。您应该在浏览器中看到一条消息,内容为
Hello World! I have been seen 1 times.
刷新页面。
数字应该递增。
Hello World! I have been seen 2 times.
切换到另一个终端窗口,然后键入
docker image ls
以列出本地镜像。此时列出镜像应该会返回
redis
和web
。$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE composetest_web latest e2c21aa48cc1 4 minutes ago 93.8MB python 3.4-alpine 84e6077c7ab6 7 days ago 82.5MB redis alpine 9d8fa9aa0e5b 3 weeks ago 27.5MB
您可以使用
docker inspect <tag or id>
检查镜像。停止应用程序,方法是在第二个终端中从项目目录内运行
docker compose down
,或者在您启动应用程序的原始终端中按CTRL+C
。
步骤 4:编辑 Compose 文件以使用 Compose Watch
编辑项目目录中的 compose.yaml
文件以使用 watch
,以便您可以预览正在运行的 Compose 服务,这些服务会在您编辑和保存代码时自动更新
services:
web:
build: .
ports:
- "8000:5000"
develop:
watch:
- action: sync
path: .
target: /code
redis:
image: "redis:alpine"
每当文件更改时,Compose 都会将文件同步到容器内 /code
下的相应位置。复制完成后,捆绑程序会更新正在运行的应用程序,而无需重新启动。
有关 Compose Watch 工作原理的更多信息,请参阅 使用 Compose Watch。或者,请参阅 管理容器中的数据 以了解其他选项。
注意
为了使本示例正常工作,
--debug
选项已添加到Dockerfile
中。Flask 中的--debug
选项启用了自动代码重新加载,这使得您可以处理后端 API,而无需重新启动或重新构建容器。更改.py
文件后,后续的 API 调用将使用新代码,但浏览器 UI 不会在此小示例中自动刷新。大多数前端开发服务器都包含与 Compose 配合使用的原生实时重新加载支持。
步骤 5:使用 Compose 重新构建和运行应用程序
从项目目录中,键入 docker compose watch
或 docker compose up --watch
以构建和启动应用程序并启动文件监视模式。
$ docker compose watch
[+] Running 2/2
✔ Container docs-redis-1 Created 0.0s
✔ Container docs-web-1 Recreated 0.1s
Attaching to redis-1, web-1
⦿ watch enabled
...
再次检查浏览器中的 Hello World
消息,然后刷新以查看计数递增。
步骤 6:更新应用程序
要查看 Compose Watch 的实际效果
更改
app.py
中的问候语并保存。例如,将Hello World!
消息更改为Hello from Docker!
return 'Hello from Docker! I have been seen {} times.\n'.format(count)
刷新浏览器中的应用程序。问候语应该已更新,计数器仍然在递增。
完成后,运行
docker compose down
。
步骤 7:拆分服务
使用多个 Compose 文件可以根据不同的环境或工作流自定义 Compose 应用程序。这对于可能使用数十个容器且所有权分布在多个团队中的大型应用程序非常有用。
在您的项目文件夹中,创建一个名为
infra.yaml
的新 Compose 文件。从您的
compose.yaml
文件中剪切 Redis 服务,并将其粘贴到新的infra.yaml
文件中。确保在文件顶部添加services
顶级属性。您的infra.yaml
文件现在应该如下所示services: redis: image: "redis:alpine"
在您的
compose.yaml
文件中,添加include
顶级属性以及infra.yaml
文件的路径。include: - infra.yaml services: web: build: . ports: - "8000:5000" develop: watch: - action: sync path: . target: /code
运行
docker compose up
以使用更新的 Compose 文件构建应用程序并运行它。您应该在浏览器中看到Hello world
消息。
这是一个简化的示例,但它演示了 include
的基本原理,以及它如何使将复杂的应用程序模块化为子 Compose 文件变得更容易。有关 include
和使用多个 Compose 文件的更多信息,请参阅 使用多个 Compose 文件。
步骤 8:尝试其他一些命令
如果您想在后台运行服务,可以将
-d
标志(表示“分离模式”)传递给docker compose up
,并使用docker compose ps
查看当前正在运行的内容$ docker compose up -d Starting composetest_redis_1... Starting composetest_web_1... $ docker compose ps Name Command State Ports ------------------------------------------------------------------------------------- composetest_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp composetest_web_1 flask run Up 0.0.0.0:8000->5000/tcp
运行
docker compose --help
以查看其他可用命令。如果您使用 `docker compose up -d` 启动 Compose,请在完成操作后停止您的服务。
$ docker compose stop
您可以使用 `docker compose down` 命令将所有内容关闭,并完全删除容器。