使用Docker Compose部署python应用

这篇文章我们通过Docker Compose来运行部署一个简单的Python web应用,我们将使用Flask框架和Redis。

预备的东西

  • 安装好Docker
  • 安装好Docker Compose

定义应用的依赖

1、创建项目目录

mkdir composetest
cd composetest

2、创建应用文件app.py

在项目根目录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)

if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

这里,redis是应用网络上edis容器的主机名,我们使用Redis的默认端口:6379。

3、创建应用requirements.txt文件

在项目根目录composetest下创建requirements.txt文件,编辑文件:

flask
redis

创建Dockerfile文件

我们写个Dockerfile文件来构建Docker镜像,该镜像会包含该Python应用的所有依赖,包括Python本身。

在项目根目录composetest下创建Dockerfile文件并编辑文件:

FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

该文件告诉Docker完成以下工作:

  • 构建一个以Python 3.4镜像为基础镜像的镜像.
  • 把当前目录 . 复制到镜像的 /code 路径下.
  • 设置工作目录为 /code .
  • 安装Python依赖.
  • 设置容器的默认命令.

在Compose文件定义服务

在项目根目录composetest下创建docker-compose.yml文件并编辑:

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

该Compose文件定义两个服务:web和redis。该web服务将

  • 使用从Dockerfile文件构建的镜像.
  • 暴露容器的5000端口映射到宿主机的5000端口。我们使用Flask的web服务器默认端口 5000.

redis服务使用从Docker Hub registry仓库拉取的公有Redis镜像。

使用Compose构建和运行app

在项目根目录composetest下启动运行应用:

$ docker-compose up
Starting composetest_web_1   ... done
Starting composetest_redis_1 ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1  | 1:C 05 May 02:38:07.354 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 05 May 02:38:07.354 # Redis version=4.0.9, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 05 May 02:38:07.354 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 05 May 02:38:07.355 * Running mode=standalone, port=6379.
redis_1  | 1:M 05 May 02:38:07.355 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 05 May 02:38:07.355 # Server initialized
redis_1  | 1:M 05 May 02:38:07.355 # 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.
redis_1  | 1:M 05 May 02:38:07.355 * DB loaded from disk: 0.000 seconds
redis_1  | 1:M 05 May 02:38:07.355 * Ready to accept connections
web_1    |  * Serving Flask app "app" (lazy loading)
web_1    |  * Environment: production
web_1    |    WARNING: Do not use the development server in a production environment.
web_1    |    Use a production WSGI server instead.
web_1    |  * Debug mode: on
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1    |  * Restarting with stat
web_1    |  * Debugger is active!
web_1    |  * Debugger PIN: 320-444-115
web_1    | 172.18.0.1 - - [05/May/2018 02:38:11] "GET / HTTP/1.1" 200 -

Compose拉取Redis镜像,为我们的应用构建一个镜像,并开始我们定义的服务。这种情况,代码在构建时是被静态地复制到镜像里。

打开浏览器,输入http://0.0.0.0:5000/, 会看到页面输出:

Hello World! I have been seen 1 times.

刷新页面,这里的数字会顺序递增

Hello World! I have been seen 2 times.

打开另一个terminal窗口,输入docker image ls可以看到本地的镜像列表,列表中会看到redis和web:

$ docker image ls
REPOSITORY                       TAG                 IMAGE ID            CREATED             SIZE
composetest_web                  latest              88cd35029579        12 hours ago        94.9MB
springio/gs-spring-boot-docker   latest              6c173fe17a59        26 hours ago        118MB
python                           3.4-alpine          42756b6e26a0        2 weeks ago         83.6MB
hello-world                      latest              e38bc07ac18e        3 weeks ago         1.85kB
redis                            alpine              98bd7cfc43b8        5 weeks ago         27.8MB
openjdk                          8-jdk-alpine        224765a6bdbe        3 months ago        102MB

要停止应用,可以输入docker-compose down命令或者按CTRL + C。

修改Compose文件

编辑docker-compose.yml,为web服务添加一个bind mount:

version: '3'
services:
  web:
    build: .
    ports:
     - "5000:5000"
    volumes:
     - .:/code
  redis:
    image: "redis:alpine"

新添加的 volume 键将宿主机的项目目录挂载到容器里的 /code 目录,这样我们可以即时地修改代码,而不用重新构建镜像。

重新构建和运行应用

项目根目录下输入 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)
...

刷新浏览器,会看到计数依然会递增。

更新应用

现在项目代码已经通过 volume 被挂载到容器,我们可以修改代码并即时看到变化,而不用重新构建镜像。我们编辑修改下 app.py文件,比如将 Hello World! 修改为 Hello from Docker!:

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

刷新浏览器,页面会相应地更新

docke-compose其他命令

在后台运行服务:

$ docker-compose up -d

查看当前运行服务:

$ docker-compose ps

查看web服务在使用的环境变量:

$ docker-compose run web env

停止服务:

$ docker-compose stop

停止并删除容器、网络、镜像和volumes卷

$ docker-compose down --volumes
标签:部署PythonDocker 发布于:2019-10-25 02:08:36