参考文档:https://docs.docker.com/compose/
docker 使我们能够把应用的各个部分单独打包成不同的 container(如把网站的 apache 放到一个 container,数据库放到另一个 container )来提高可靠性和实现更灵活的配置。然而每次都得打开一堆 container 才能打开一个应用显得并不方便,Docker Compose 就是用来解决这个痛点的。
Docker Compose 定义:定义和运行多个 docker container 的工具。你只需要在一个文件中定义一个多 container 的应用,然后就能通过一条命令来管理这个应用了。
Compose 对于开发环境、演示环境及 CI 环境中相当实用,然而目前官方并不推荐在生产环境中使用它。
使用 Compose 主要有 3 步:
Dockerfile
定义你的应用的环境(一个 Dockerfile 对应一个 container)docker-compose.yml
定义你的应用需要用到的服务。docker-compose up
,Compose 就会启动你的整个应用及所需要的服务。docker-compose.yml
大致格式如下:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
links:
- redis
redis:
image: redis
Compose 的命令主要有:
以一个 python 应用为例子介绍 compose 的使用
首先,安装 docker 和 compose。目前 docker-toolbox 中已经自带了 compose ,因此 mac/windows 上不需要额外安装了。
然后,为你的项目建立一个文件夹:
$ mkdir composetest
$ cd composetest
创建一个 app.py
文件。文件中使用了 Flask 和 Redis ,因此,我们后面定义服务的时候会为这两个服务创建 container
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello World! I have been seen %s times.' % redis.get('hits')
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
在 requirement.txt
文件中定义 python 的依赖:
flask
redis
创建 Dockerfile
文件:
# Build an image starting with the Python 2.7 image.
FROM python:2.7
# Add the current directory . into the path /code in the image.
ADD . /code
# Set the working directory to /code.
WORKDIR /code
# Install your Python dependencies.
RUN pip install -r requirements.txt
# Set the default command for the container to python app.py
CMD python app.py
重头戏来了。创建一个 docker-compose.yml
来定义一系列服务:
web:
# Builds from the Dockerfile in the current directory.
build: .
# Forwards the exposed port 5000 on the container to port 5000 on the host machine.
ports:
- "5000:5000"
# Mounts the current directory on the host to /code inside the container allowing you to modify the code without having to rebuild the image.
volumes:
- .:/code
# Connects the web container to the Redis service via a link.
links:
- redis
redis:
# Uses the public Redis image which gets pulled from the Docker Hub registry.
image: redis
$ docker-compose up
Starting composetest_redis_1...
Recreating composetest_web_1...
Attaching to composetest_redis_1, composetest_web_1
redis_1 | 1:C 23 Aug 13:22:40.241 # 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 | _._
redis_1 | _.-``__ ''-._
redis_1 | _.-`` `. `_. ''-._ Redis 3.0.3 (00000000/0) 64 bit
redis_1 | .-`` .-
. \/ _.,_ ''-._
redis_1 | ( ' , .-` | `, ) Running in standalone mode
redis_1 | |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
redis_1 | | `-._ `._ / _.-' | PID: 1
redis_1 | `-._ `-._ `-./ _.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' | http://redis.io
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' |
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | `-._ `-.__.-' _.-'
redis_1 | `-._ _.-'
redis_1 | `-.__.-'
redis_1 |
redis_1 | 1:M 23 Aug 13:22:40.246 # Server started, Redis version 3.0.3
redis_1 | 1:M 23 Aug 13:22:40.246 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 23 Aug 13:22:40.246 # 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 23 Aug 13:22:40.246 # 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 23 Aug 13:22:40.246 * The server is now ready to accept connections on port 6379
redis_1 | 1:C 23 Aug 13:51:27.093 # 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 | _._
redis_1 | _.-``__ ''-._
redis_1 | _.-`` `. `_. ''-._ Redis 3.0.3 (00000000/0) 64 bit
redis_1 | .-`` .-
. \/ _.,_ ''-._
redis_1 | ( ' , .-` | `, ) Running in standalone mode
redis_1 | |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
redis_1 | | `-._ `._ / _.-' | PID: 1
redis_1 | `-._ `-._ `-./ _.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' | http://redis.io
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' |
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | `-._ `-.__.-' _.-'
redis_1 | `-._ _.-'
redis_1 | `-.__.-'
redis_1 |
redis_1 | 1:M 23 Aug 13:51:27.095 # Server started, Redis version 3.0.3
redis_1 | 1:M 23 Aug 13:51:27.095 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 23 Aug 13:51:27.095 # 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 23 Aug 13:51:27.095 # 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 23 Aug 13:51:27.095 * The server is now ready to accept connections on port 6379
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1 | * Restarting with stat
可通过在浏览器中打开 http://192.168.99.100:5000
查看网页。此时会看到网页中显示:
Hello World! I have been seen 1 times.
同时命令行中会显示网络请求的 log :
web_1 | 192.168.99.1 - - [23/Aug/2015 13:52:34] "GET / HTTP/1.1" 200 -
web_1 | 192.168.99.1 - - [23/Aug/2015 13:52:34] "GET /favicon.ico HTTP/1.1" 404 -
$ docker-compose ps
composetest_redis_1 /entrypoint.sh redis-server Up 6379/tcp
composetest_web_1 /bin/sh -c python app.py Up 0.0.0.0:5000->5000/tcp
* 在单独服务中运行命令,如在 web 这个服务中查看环境变量:
$ docker-compose run web env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=7681a42c0560
TERM=xterm
COMPOSETEST_WEB_1_PORT=tcp://172.17.0.15:5000
COMPOSETEST_WEB_1_PORT_5000_TCP=tcp://172.17.0.15:5000
COMPOSETEST_WEB_1_PORT_5000_TCP_ADDR=172.17.0.15
COMPOSETEST_WEB_1_PORT_5000_TCP_PORT=5000
COMPOSETEST_WEB_1_PORT_5000_TCP_PROTO=tcp
COMPOSETEST_WEB_1_NAME=/composetest_web_run_1/composetest_web_1
COMPOSETEST_WEB_1_ENV_affinity:container==6edaa1eb27095dd320de439516f28a1431169949c49a2588a72a9520a97d6ff2
COMPOSETEST_WEB_1_ENV_LANG=C.UTF-8
COMPOSETEST_WEB_1_ENV_PYTHON_VERSION=2.7.10
COMPOSETEST_WEB_1_ENV_PYTHON_PIP_VERSION=7.1.1
REDIS_PORT=tcp://172.17.0.14:6379
REDIS_PORT_6379_TCP=tcp://172.17.0.14:6379
REDIS_PORT_6379_TCP_ADDR=172.17.0.14
REDIS_PORT_6379_TCP_PORT=6379
REDIS_PORT_6379_TCP_PROTO=tcp
REDIS_NAME=/composetest_web_run_1/redis
REDIS_ENV_REDIS_VERSION=3.0.3
REDIS_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.0.3.tar.gz
REDIS_ENV_REDIS_DOWNLOAD_SHA1=0e2d7707327986ae652df717059354b358b83358
REDIS_1_PORT=tcp://172.17.0.14:6379
REDIS_1_PORT_6379_TCP=tcp://172.17.0.14:6379
REDIS_1_PORT_6379_TCP_ADDR=172.17.0.14
REDIS_1_PORT_6379_TCP_PORT=6379
REDIS_1_PORT_6379_TCP_PROTO=tcp
REDIS_1_NAME=/composetest_web_run_1/redis_1
REDIS_1_ENV_REDIS_VERSION=3.0.3
REDIS_1_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.0.3.tar.gz
REDIS_1_ENV_REDIS_DOWNLOAD_SHA1=0e2d7707327986ae652df717059354b358b83358
WEB_PORT=tcp://172.17.0.15:5000
WEB_PORT_5000_TCP=tcp://172.17.0.15:5000
WEB_PORT_5000_TCP_ADDR=172.17.0.15
WEB_PORT_5000_TCP_PORT=5000
WEB_PORT_5000_TCP_PROTO=tcp
WEB_NAME=/composetest_web_run_1/web
WEB_ENV_affinity:container==6edaa1eb27095dd320de439516f28a1431169949c49a2588a72a9520a97d6ff2
WEB_ENV_LANG=C.UTF-8
WEB_ENV_PYTHON_VERSION=2.7.10
WEB_ENV_PYTHON_PIP_VERSION=7.1.1
WEB_1_PORT=tcp://172.17.0.15:5000
WEB_1_PORT_5000_TCP=tcp://172.17.0.15:5000
WEB_1_PORT_5000_TCP_ADDR=172.17.0.15
WEB_1_PORT_5000_TCP_PORT=5000
WEB_1_PORT_5000_TCP_PROTO=tcp
WEB_1_NAME=/composetest_web_run_1/web_1
WEB_1_ENV_affinity:container==6edaa1eb27095dd320de439516f28a1431169949c49a2588a72a9520a97d6ff2
WEB_1_ENV_LANG=C.UTF-8
WEB_1_ENV_PYTHON_VERSION=2.7.10
WEB_1_ENV_PYTHON_PIP_VERSION=7.1.1
COMPOSETEST_REDIS_1_PORT=tcp://172.17.0.14:6379
COMPOSETEST_REDIS_1_PORT_6379_TCP=tcp://172.17.0.14:6379
COMPOSETEST_REDIS_1_PORT_6379_TCP_ADDR=172.17.0.14
COMPOSETEST_REDIS_1_PORT_6379_TCP_PORT=6379
COMPOSETEST_REDIS_1_PORT_6379_TCP_PROTO=tcp
COMPOSETEST_REDIS_1_NAME=/composetest_web_run_1/composetest_redis_1
COMPOSETEST_REDIS_1_ENV_REDIS_VERSION=3.0.3
COMPOSETEST_REDIS_1_ENV_REDIS_DOWNLOAD_URL=http://download.redis.io/releases/redis-3.0.3.tar.gz
COMPOSETEST_REDIS_1_ENV_REDIS_DOWNLOAD_SHA1=0e2d7707327986ae652df717059354b358b83358
LANG=C.UTF-8
PYTHON_VERSION=2.7.10
PYTHON_PIP_VERSION=7.1.1
HOME=/root
* 停止应用(对应后台运行。若没加 `-d` 则直接 ctrl+c 即可)
$ docker-compose stop
Stopping composetest_web_1... done
Stopping composetest_redis_1... done
## 遇到的问题
1. 在 build server 的过程中出现此错误:
Collecting redis (from -r requirements.txt (line 2))
Downloading redis-2.10.3.tar.gz (86kB)
Exception:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/pip/basecommand.py", line 211, in main
status = self.run(options, args)
File "/usr/local/lib/python2.7/site-packages/pip/commands/install.py", line 305, in run
wb.build(autobuilding=True)
File "/usr/local/lib/python2.7/site-packages/pip/wheel.py", line 705, in build
self.requirement_set.prepare_files(self.finder)
File "/usr/local/lib/python2.7/site-packages/pip/req/req_set.py", line 334, in prepare_files
functools.partial(self._prepare_file, finder))
File "/usr/local/lib/python2.7/site-packages/pip/req/req_set.py", line 321, in _walk_req_to_install
more_reqs = handler(req_to_install)
File "/usr/local/lib/python2.7/site-packages/pip/req/req_set.py", line 491, in _prepare_file
session=self.session)
File "/usr/local/lib/python2.7/site-packages/pip/download.py", line 825, in unpack_url
session,
File "/usr/local/lib/python2.7/site-packages/pip/download.py", line 673, in unpack_http_url
from_path, content_type = _download_http_url(link, session, temp_dir)
File "/usr/local/lib/python2.7/site-packages/pip/download.py", line 886, in _download_http_url
_download_url(resp, link, content_file)
File "/usr/local/lib/python2.7/site-packages/pip/download.py", line 621, in _download_url
for chunk in progress_indicator(resp_read(4096), 4096):
File "/usr/local/lib/python2.7/site-packages/pip/utils/ui.py", line 133, in iter
for x in it:
File "/usr/local/lib/python2.7/site-packages/pip/download.py", line 586, in resp_read
decode_content=False):
File "/usr/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/response.py", line 307, in stream
data = self.read(amt=amt, decode_content=decode_content)
File "/usr/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/response.py", line 267, in read
raise ReadTimeoutError(self._pool, None, 'Read timed out.')
ReadTimeoutError: HTTPSConnectionPool(host='pypi.python.org', port=443): Read timed out.
You are using pip version 7.1.1, however version 7.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
Service 'web' failed to build: The command '/bin/sh -c pip install -r requirements.txt' returned a non-zero code: 2
**解决方法**
在 Dockerfile 中添加一行:
FROM python:2.7
ADD . /code
WORKDIR /code
RUN pip install --upgrade pip # add this line to upgrade pip first
RUN pip install -r requirements.txt
CMD python app.py
添加后问题解决。