On this page

Docker Compose

本教程旨在介绍 Docker Compose 的关键概念,同时构建一个简单的 Python Web 应用程序。该应用程序使用 Flask 框架并在 Redis 中维护一个点击计数器。 即使您不熟悉 Python,这里演示的概念也应该是可以理解的。

您不需要安装 Python 或 Redis,因为两者都是由 Docker 镜像提供的。

步骤 1:定义应用程序依赖

  1. 为项目创建一个目录:
    $ mkdir composetest
    $ cd composetest
    
  2. 在项目目录中创建一个名为的文件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 服务需要在应用程序的生命周期内随时重新启动,这也会使应用程序更具弹性。在集群中,这还有助于处理节点之间的瞬时连接丢失。

  3. 在项目目录中创建另一个名为的文件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 文件定义了两个服务:webredis​​ 。 该服务使用从当前目录中web构建的图像。Dockerfile然后,它将容器和主机绑定到公开的端口8000。此示例服务使用 Flask Web 服务器的默认端口5000。 该服务使用 从 Docker Hub 注册表中提取的redis公共 Redis映像。

第 4 步:使用 Compose 构建并运行您的应用程序

  1. 从您的项目目录中,通过运行启动您的应用程序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 映像,为您的代码构建映像,并启动您定义的服务。在这种情况下,代码会在构建时静态复制到映像中。

  2. 在浏览器中输入 http://localhost:8000/ 以查看应用程序正在运行。 如果这不能解决问题,您还可以尝试 http://127.0.0.1:8000。 您应该在浏览器中看到一条消息:

    Hello World! I have been seen 1 times.
    
  3. 刷新页面。 该数字应该增加。

    Hello World! I have been seen 2 times.
    
  4. 切换到另一个终端窗口,然后键入docker image ls以列出本地图像。 此时列出图像应该返回redisweb

    $ 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>

  5. 停止应用程序,可以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 WorldWeb 浏览器中的消息,然后刷新以查看计数增量。

第 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