Docker Compose
本教程旨在介绍 Docker Compose 的关键概念,同时构建一个简单的 Python Web 应用程序。该应用程序使用 Flask 框架并在 Redis 中维护一个点击计数器。 即使您不熟悉 Python,这里演示的概念也应该是可以理解的。
您不需要安装 Python 或 Redis,因为两者都是由 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 容器的主机名。我们使用 Redis 的默认端口6379
. >处理瞬态错误get_hit_count
请注意该函数的编写方式。如果 redis 服务不可用,这个基本的重试循环允许我们多次尝试我们的请求。这在应用程序上线时启动时非常有用,而且如果 Redis 服务需要在应用程序的生命周期内随时重新启动,这也会使应用程序更具弹性。在集群中,这还有助于处理节点之间的瞬时连接丢失。 - 在项目目录中创建另一个名为的文件
requirements.txt
,并将以下代码粘贴到:flask redis
第 2 步:创建 Dockerfile
Dockerfile 用于构建 Docker 镜像。该映像包含 Python 应用程序所需的所有依赖项,包括 Python 本身。
在您的项目目录中,创建一个名为的文件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"]
这告诉 Docker:
- 从 Python 3.10 映像开始构建映像。
- 将工作目录设置为
/code
. - 设置命令使用的环境变量
flask
。 - 安装gcc和其他依赖项
- 复制
requirements.txt
并安装 Python 依赖项。 - 向镜像添加元数据以描述容器正在侦听端口 5000
.
将项目中的当前目录复制到.
镜像中的workdir。- 将容器的默认命令设置为
flask run
。
>重要的
检查是否Dockerfile
没有像.txt
. 某些编辑器可能会自动附加此文件扩展名,这会在您运行应用程序时导致错误。
步骤 3:在 Compose 文件中定义服务
compose.yaml
在项目目录中创建一个名为的文件并粘贴以下内容:
services:
web:
build: .
ports:
- "8000:5000"
redis:
image: "redis:alpine"
此 Compose 文件定义了两个服务:web
和redis
。
该服务使用从当前目录中web
构建的图像。Dockerfile
然后,它将容器和主机绑定到公开的端口8000
。此示例服务使用 Flask Web 服务器的默认端口5000
。
该服务使用 从 Docker Hub 注册表中提取的redis
公共 Redis映像。
第 4 步:使用 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。
步骤 5:编辑 Compose 文件以添加绑定挂载
编辑compose.yaml
项目目录中的文件以添加 服务的绑定挂载web
:
services:
web:
build: .
ports:
- "8000:5000"
volumes:
- .:/code
environment:
FLASK_DEBUG: "true"
redis:
image: "redis:alpine"
新volumes
密钥将主机上的项目目录(当前目录)挂载到/code
容器内部,允许您动态修改代码,而无需重建映像。关键environment
设置 FLASK_DEBUG
环境变量,它告诉flask run
在开发模式下运行并在更改时重新加载代码。该模式仅应在开发中使用。
第 6 步:使用 Compose 重新构建并运行应用程序
从项目目录中,键入docker compose up
使用更新的 Compose 文件构建应用程序,然后运行它。
$ 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)
...
再次检查Hello World
Web 浏览器中的消息,然后刷新以查看计数增量。
第 7 步:更新应用程序
由于应用程序代码现在使用卷安装到容器中,因此您可以更改其代码并立即查看更改,而无需重建映像。
更改问候语app.py
并保存。例如,将Hello World!
消息更改为Hello from Docker!
:
return 'Hello from Docker! I have been seen {} times.\n'.format(count)
在浏览器中刷新应用程序。问候语应该更新,并且计数器应该仍然递增。
第 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 run
命令允许您为您的服务运行一次性命令。例如,要查看服务可以使用哪些环境变量 web
:
$ docker compose run web env
查看docker compose --help
其他可用命令。
如果您使用 启动 Compose docker compose up -d
,请在完成服务后停止它们:
$ docker compose stop
您可以使用该命令关闭所有内容,完全删除容器down
。传递--volumes
以同时删除 Redis 容器使用的数据卷:
$ docker compose down --volumes