Get started with Docker Compose

预计阅读时间:11分钟

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

Prerequisites

确保您已经安装了Docker EngineDocker Compose . 您不需要安装 Python 或 Redis,因为它们都是由 Docker 映像提供的.

Step 1: Setup

定义应用程序依赖项.

  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
    

Step 2: Create a 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
  • 复制当前目录. 在项目中到 workdir . 在图像中.
  • 将容器的默认命令设置为flask run .

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

Step 3: Define services in a Compose file

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

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

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

Web service

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

Redis service

redis服务使用从 Docker Hub 注册表中提取的公共Redis映像.

Step 4: Build and run your app with 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/ 以查看正在运行的应用程序.

    如果您在 Linux、Docker Desktop for Mac 或 Docker Desktop for Windows 上本地使用 Docker,那么 Web 应用程序现在应该在您的 Docker 守护程序主机上的端口 8000 上进行侦听. 将您的 Web 浏览器指向 http://localhost:8000 以查找Hello World消息. 如果这不能解决,您也可以尝试 http://127.0.0.1:8000.

    您应该会在浏览器中看到一条消息:

    Hello World! I have been seen 1 times.
    

    hello world in browser

  3. 刷新页面.

    数字应该增加.

    Hello World! I have been seen 2 times.
    

    hello world in browser

  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.

Step 5: Edit the Compose file to add a bind mount

编辑项目目录中docker-compose.ymlweb服务添加绑定挂载

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

新的volumes键将主机上的项目目录(当前目录)挂载到容器内的/code中,允许您即时修改代码,而无需重建映像. environment键设置FLASK_ENV环境变量,它告诉flask run在开发模式下运行并在更改时重新加载代码. 这种模式应该只在开发中使用.

Step 6: Re-build and run the app with 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)
...

再次在 Web 浏览器中检查Hello World消息,然后刷新以查看计数增量.

共享文件夹、卷和绑定装载

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

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

Step 7: Update the application

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

Change the greeting in app.py and save it. For example, change the Hello World! message to Hello from Docker!:

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

在浏览器中刷新应用程序. 应更新问候语,并且计数器仍应递增.

hello world in browser

Step 8: Experiment with some other commands

如果要在后台运行服务,可以将-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以查看其他可用命令. 您还可以为 bash 和 zsh shell 安装命令完成,它还会显示可用的命令.

如果您使用docker-compose up -d启动 Compose,请在完成后停止服务:

$ docker-compose stop

您可以使用down命令关闭所有内容,完全移除容器. 通过--volumes也可以删除 Redis 容器使用的数据卷:

$ docker-compose down --volumes

至此,您已经了解了 Compose 的基本工作原理.

Where to go next

documentation, docs, docker, compose, orchestration, containers

by  icopy.site