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

先决条件

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

第1步:安装

定义应用程序依赖项。

  1. 为项目创建一个目录:
<span style="color:#333333"><code>$ mkdir composetest
$ cd composetest
</code></span>
  1. 创建一个app.py在项目目录中调用的文件并将其粘贴到:
<span style="color:#333333"><code>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)

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)
</code></span>

在此示例中,redis是应用程序网络上redis容器的主机名。我们使用Redis的默认端口6379

处理瞬态错误

注意get_hit_count函数的编写方式。如果redis服务不可用,这个基本的重试循环允许我们多次尝试我们的请求。这在应用程序联机时启动时非常有用,但如果需要在应用程序生命周期内的任何时间重新启动Redis服务,这也会使我们的应用程序更具弹性。在群集中,这还有助于处理节点之间的瞬时连接丢弃。

  1. 创建requirements.txt项目目录中调用的另一个文件并将其粘贴到:
<span style="color:#333333"><code>flask
redis
</code></span>

第2步:创建Dockerfile

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

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

<span style="color:#33444c"><span style="color:#333333"><code>FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
</code></span></span>

这告诉Docker:

  • 从Python 3.4映像开始构建映像。
  • 将当前目录添加./code映像中的路径中。
  • 将工作目录设置为/code
  • 安装Python依赖项。
  • 将容器的默认命令设置为python app.py

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

第3步:在Compose文件中定义服务

创建docker-compose.yml在项目目录中调用的文件并粘贴以下内容:

<span style="color:#33444c"><span style="color:#333333"><code>version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
  redis:
    image: "redis:alpine"
</code></span></span>

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

网络服务

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

Redis服务

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

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

  1. 从项目目录中,通过运行启动应用程序docker-compose up
<span style="color:#333333"><code>$ 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
</code></span>

Compose拉取Redis图像,为您的代码构建图像,并启动您定义的服务。在这种情况下,代码在构建时静态复制到映像中。

  1. http://0.0.0.0:5000/在浏览器中输入以查看正在运行的应用程序。
    如果您在Linux,Docker Desktop for Mac或Docker Desktop for Windows上本机使用Docker,那么Web应用程序现在应该在Docker守护程序主机上的端口5000上进行侦听。指向您的Web浏览器http://localhost:5000以查找Hello World消息。如果这不能解决,您也可以尝试 http://0.0.0.0:5000
    如果您在Mac或Windows上使用Docker Machine,请使用docker-machine ip MACHINE_VM获取Docker主机的IP地址。然后,http://MACHINE_VM_IP:5000在浏览器中打开 。
    您应该在浏览器中看到一条消息:
<span style="color:#333333"><code>Hello World! I have been seen 1 times.
</code></span>

docker compose设置容器编码格式 docker compose -f_docker

  1. 刷新页面。
    数字应该增加。
<span style="color:#333333"><code>Hello World! I have been seen 2 times.
</code></span>

docker compose设置容器编码格式 docker compose -f_docker-compose_02

  1. 切换到另一个终端窗口,然后键入docker image ls以列出本地图像。
    此时列出图像应返回redisweb
<span style="color:#333333"><code>$ 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
</code></span>

你可以检查图像docker inspect <tag or id>

  1. 通过docker-compose down 在第二个终端的项目目录中运行,或者在启动应用程序的原始终端中按CTRL + C来停止应用程序。

步骤5:编辑Compose文件以添加绑定装载

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

<span style="color:#33444c"><span style="color:#333333"><code>version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: "redis:alpine"
</code></span></span>

volumes密钥将主机上的项目目录(当前目录)/code安装到容器内,允许您动态修改代码,而无需重建映像。

第6步:使用Compose重新构建并运行应用程序

从项目目录中,键入docker-compose up以使用更新的Compose文件构建应用程序,然后运行它。

<span style="color:#33444c"><span style="color:#333333"><code>$ 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)
...
</code></span></span>

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

共享文件夹,卷和绑定装入

  • 如果您的项目位于Users目录(cd ~)之外,则需要共享Dockerfile的驱动器或位置以及您正在使用的卷。如果您收到运行时错误,指示未找到应用程序文件,则会拒绝卷装入,或者服务无法启动,请尝试启用文件或驱动器共享。卷安装需要共享驱动器用于C:\Users(Windows)或/Users(Mac)之外的项目 ,并且对于使用Linux容器的 Docker Desktop for Windows上的任何项目都是必需的。有关更多信息,请参阅 适用于Windows的Docker Desktop上的共享驱动器,适用于Mac的Docker上的文件共享以及有关如何管理容器中数据的一般示例。
  • 如果您在较旧的Windows操作系统上使用Oracle VirtualBox,则可能会遇到此虚拟机故障单中所述的共享文件夹问题。较新的Windows系统满足Docker Desktop for Windows的要求,不需要VirtualBox。

第7步:更新应用程序

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

  1. 更改问候语app.py并保存。例如,将Hello World!邮件更改为Hello from Docker!
<span style="color:#333333"><code>return 'Hello from Docker! I have been seen {} times.\n'.format(count)
</code></span>
  1. 在浏览器中刷新应用程序。问候语应该更新,计数器仍然应该递增。

第8步:尝试其他一些命令

如果要在后台运行服务,可以将-d标志(用于“分离”模式)传递给docker-compose up并使用docker-compose ps以查看当前正在运行的内容:

<span style="color:#33444c"><span style="color:#333333"><code>$ docker-compose up -d
Starting composetest_redis_1...
Starting composetest_web_1...

$ docker-compose ps
Name                 Command            State       Ports
-------------------------------------------------------------------
composetest_redis_1   /usr/local/bin/run         Up
composetest_web_1     /bin/sh -c python app.py   Up      5000->5000/tcp
</code></span></span>

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

<span style="color:#33444c"><span style="color:#333333"><code>$ docker-compose run web env
</code></span></span>

docker-compose --help参阅其他可用命令。您还可以为bash和zsh shell 安装命令完成,它还会显示可用的命令。

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

<span style="color:#33444c"><span style="color:#333333"><code>$ docker-compose stop
</code></span></span>

您可以使用该down 命令将所有内容放下,完全删除容器。传递--volumes还删除Redis容器使用的数据卷:

<span style="color:#33444c"><span style="color:#333333"><code>$ docker-compose down --volumes
</code></span></span>

此时,您已经了解了Compose如何工作的基础知识。