用python语言开发一个web应用,redis统计访问次数。先安装docker引擎与compse,无需安装python、redis,由compose负责。
$ mkdir composetest
$ cd 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作为主机名连接redis服务,那么想当然的,docker一定提供了名称解析服务,最终将redis映射成容器实例的IP地址。在app.run函数中没有指定端口号,flask默认是5000。
创建 requirements.txt文件,内容如下:
flask
redis
命名为Dockerfile,内容如下:
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
注意,其中并没有指定web服务暴露的端口号。
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis:alpine"
定义了两个服务,一个是web,另一个是redis,对于web定义了内外端口的映射关系,使用docker compose默认创建的网络。
第四步:用compose构建并运行app
$ 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
完成以后可以通过浏览器确认结果。
将宿主机包含代码的目录挂载到服务,本质就是容器实例与宿主机共享文件。
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
redis:
image: "redis:alpine"
注意其中的volumes,意思是将当前目录挂载到容器实例的/code目录下。实际上在第二步中的Dockerfile文件中,已经通过Add命令将当前目录下的文件加入到镜像中,意思是此时有两份目录,宿主机一份,容器实例一份,彼此没有关系。当在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)
...
此时,如果在本地修改app.py文件的内容,容器实例也会受影响,因为两者在共享同一份文件。
$ 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
-d表示后台运行,ps用来查看。
$ docker-compose run web env
显示某个服务的环境变量。
docker-compose stop
停止compose的运行。
$ docker-compose down --volumes
彻底清除。包括容器在运行时生成的可读写层。后边的--volumes表示清除存储。主要是redis容器在运行时,为了保持状态,占用了宿主机上的存储空间。如果不指定,将不会删除。这样是彻底删除。
总结:这样看来compose用来打包测试环境,跑测试是非常方便的。