这篇文章我们通过Docker Compose来运行部署一个简单的Python web应用,我们将使用Flask框架和Redis。
mkdir composetest
cd composetest
在项目根目录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。
在项目根目录composetest下创建requirements.txt文件,编辑文件:
flask
redis
我们写个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完成以下工作:
在项目根目录composetest下创建docker-compose.yml文件并编辑:
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
该Compose文件定义两个服务:web和redis。该web服务将
redis服务使用从Docker Hub registry仓库拉取的公有Redis镜像。
在项目根目录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。
编辑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)
刷新浏览器,页面会相应地更新
在后台运行服务:
$ docker-compose up -d
查看当前运行服务:
$ docker-compose ps
查看web服务在使用的环境变量:
$ docker-compose run web env
停止服务:
$ docker-compose stop
停止并删除容器、网络、镜像和volumes卷
$ docker-compose down --volumes