Docker Docker Compose 初探记录

陈恒捷 · 2015年08月24日 · 1250 次阅读
本帖已被设为精华帖!

参考文档:https://docs.docker.com/compose/

docker 使我们能够把应用的各个部分单独打包成不同的 container(如把网站的 apache 放到一个 container,数据库放到另一个 container )来提高可靠性和实现更灵活的配置。然而每次都得打开一堆 container 才能打开一个应用显得并不方便,Docker Compose 就是用来解决这个痛点的。

总体介绍

Docker Compose 定义:定义和运行多个 docker container 的工具。你只需要在一个文件中定义一个多 container 的应用,然后就能通过一条命令来管理这个应用了。

Compose 对于开发环境、演示环境及 CI 环境中相当实用,然而目前官方并不推荐在生产环境中使用它。

使用 Compose 主要有 3 步:

  1. 使用 Dockerfile 定义你的应用的环境(一个 Dockerfile 对应一个 container)
  2. 使用 docker-compose.yml 定义你的应用需要用到的服务。
  3. 运行 docker-compose up ,Compose 就会启动你的整个应用及所需要的服务。

docker-compose.yml 大致格式如下:

web:
  build: .
  ports:
   - "5000:5000"
  volumes:
   - .:/code
  links:
   - redis
redis:
  image: redis

Compose 的命令主要有:

  • Start, stop 和 rebuild 服务
  • 查看正在运行的服务的状态
  • 把服务的输出 log 变成流
  • 在服务中运行单条指令(one-off)

快速入门

以一个 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

创建 Docker image

创建 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

使用 Compose 来 build 和运行你的应用

  • 启动应用: $ 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 up -d Starting composetest_redis_1... Starting composetest_web_1...

$ docker-compose ps

Name Command State Ports

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


添加后问题解决。
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册