开始使用Docker Compose

预计阅读时间:11分钟

在此页面上,您将构建一个运行在Docker Compose上的简单Python Web应用程序。该应用程序使用Flask框架,并在Redis中维护一个计数器。尽管该示例使用Python,但即使您不熟悉此处演示的概念,也应可以理解。

先决条件

确保您已经安装了Docker EngineDocker Compose。您无需安装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

在此步骤中,您将编写一个构建Docker映像的Dockerfile。该图像包含Python应用程序所需的所有依赖关系,包括Python本身。

在您的项目目录中,创建一个名为的文件Dockerfile并粘贴以下内容:

# syntax=docker/dockerfile:1
FROM python:3.7-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.7映像开始构建映像。
  • 将工作目录设置为/code
  • 设置flask命令使用的环境变量。
  • 安装gcc和其他依赖项
  • 复制requirements.txt并安装Python依赖项。
  • 将元数据添加到图像以描述容器正在侦听端口5000
  • .项目中的当前目录复制到.映像中的工作目录。
  • 将容器的默认命令设置为flask run

有关如何编写Dockerfile的更多信息,请参阅《 Docker用户指南》 和《Dockerfile参考》

步骤3:在撰写文件中定义服务

docker-compose.yml在您的项目目录中创建一个名为的文件,然后粘贴以下内容:

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

该Compose文件定义了两个服务:webredis

网络服务

web服务使用从Dockerfile当前目录中构建的映像。然后,它将容器和主机绑定到暴露的端口5000。此示例服务使用Flask Web服务器的默认端口5000

Redis服务

redis服务使用 从Docker Hub注册表中提取的公共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:5000 /以查看该应用程序正在运行。

    如果您在Linux,Mac的Docker Desktop或Windows的Docker Desktop上本地使用Docker,则Web应用程序现在应该在Docker守护程序主机上的端口5000上进行侦听。将您的Web浏览器指向http:// localhost:5000以查找Hello World消息。如果仍然无法解决,您也可以尝试http://127.0.0.1:5000。

    如果您在Mac或Windows上使用Docker Machine,请使用docker-machine ip MACHINE_VM来获取Docker主机的IP地址。然后,http://MACHINE_VM_IP:5000在浏览器中打开 。

    您应该在浏览器中看到一条消息,内容为:

    Hello World! I have been seen 1 times.
    

    浏览器中的Hello World

  3. 刷新页面。

    该数字应递增。

    Hello World! I have been seen 2 times.
    

    浏览器中的Hello World

  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文件以添加绑定挂载

编辑docker-compose.yml在项目目录添加 绑定安装web服务:

version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/code
    environment:
      FLASK_ENV: development
  redis:
    image: "redis:alpine"

volumes密钥将主机上的项目目录(当前目录)/code安装到容器内部,使您可以即时修改代码,而不必重建映像。该environment键设置了 FLASK_ENV环境变量,该变量指示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浏览器中检查消息,然后刷新以查看计数增量。

共享文件夹,卷和绑定挂载

  • 如果您的项目不在Users目录(cd ~)内,则需要共享所使用的Dockerfile和卷的驱动器或位置。如果出现运行时错误指示未找到应用程序文件,拒绝卷安装或服务无法启动,请尝试启用文件或驱动器共享。卷挂载需要用于C:\Users(Windows)或/Users(Mac)之外的项目的共享驱动器 ,并且对于使用Linux容器的Windows Docker Desktop上的任何项目都是必需的。有关更多信息,请参阅适用于Mac的Docker上的文件共享,以及有关如何管理容器中数据的一般示例 。

  • 如果您在较旧的Windows操作系统上使用Oracle VirtualBox,则可能会遇到共享文件夹的问题,如此VB故障单所述。较新的Windows系统满足Windows的Docker桌面的要求,并且不需要VirtualBox。

步骤7:更新应用程序

因为现在应用程序代码是使用卷安装到容器中的,所以您可以对其代码进行更改并立即查看更改,而无需重建映像。

更改问候语app.py并保存。例如,将Hello World! 消息更改为Hello from Docker!

return 'Hello from Docker! I have been seen {} times.\n'.format(count)

在浏览器中刷新应用。问候语应更新,并且计数器应仍在增加。

浏览器中的Hello World

步骤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:5000->5000/tcp

docker-compose run命令允许您为服务运行一次性命令。例如,查看哪些环境变量可用于 web服务:

$ docker-compose run web env

请参阅docker-compose --help以查看其他可用命令。您还可以为bash和zsh shell安装命令完成功能,这还将显示可用的命令。

如果您开始使用Compose with docker-compose up -d,请在完成服务后停止它们:

$ docker-compose stop

您可以使用down 命令降低所有内容,完全删除容器。通过--volumes还删除Redis容器使用的数据量:

$ docker-compose down --volumes

至此,您已经了解了Compose的工作原理。

接下来要去哪里

文档docsdockercompose编排容器