Docker Compose 快速入门
本教程旨在通过引导您开发一个基本的Python网络应用程序,介绍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 f'Hello World! I have been seen {count} times.\n'在这个例子中,
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要:
- Build an image starting with the Python 3.10 image.
- Set the working directory to
/code. - Set environment variables used by the
flaskcommand. - Install gcc and other dependencies
- Copy
requirements.txtand install the Python dependencies. - Add metadata to the image to describe that the container is listening on port 5000
- Copy the current directory
.in the project to the workdir.in the image. - Set the default command for the container to
flask run --debug.
重要
检查
Dockerfile没有像.txt这样的文件扩展名。一些编辑器可能会自动附加此文件扩展名,这会导致在运行应用程序时出现错误。有关如何编写Dockerfiles的更多信息,请参阅 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 connectionsCompose 拉取一个 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来检查镜像。停止应用程序,可以通过在第二个终端的项目目录中运行
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 下的相应位置。一旦复制完成,bundler 会更新正在运行的应用程序而无需重启。
有关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 f'Hello from Docker! I have been seen {count} times.\n'在浏览器中刷新应用程序。问候语应该会更新,计数器应该仍然在递增。

完成后,运行
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命令完全移除容器,将所有内容关闭。