Docker Compose简介及示例

Compose项目简介

在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。Docker开源项目Compose专门负责实现对Docker容器集群的快速编排,官方是这样定义的:Compose是一个用于定义和运行多个Docker容器的工具。使用Compose,你可以使用YAML文件来配置应用程序的服务。
Compose中两个重要概念:

  • 服务:一个应用的容器,实际上可以包括若个运行相同镜像的容器实例;
  • 项目:一组关联的应用容器组成的一个完整业务单元

Compose工具需要单独安装,具体安装办法就不说了,可以自行google。

Docker Compose示例

下面的示例将会在Docker Compose上构建一个简单的Python web应用程序,该程序使用Flask框架,并在Redis中维护一个计数器。虽然示例使用Python,但是即使你不熟悉,照样也可以理解后面所讲的内容。

前提条件

确保你已经安装了Docker EngineDocker Compose,你不需要安装PythonRedis,因为这两个都是由Docker镜像提供的。

开始构建

1.创建一个工程目录

$ mkdir composetest
$ cd composetest

2.在你新创建的目录下,生成一个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容器的主机名,这里使用Redis的默认端口6379
3.在你当前目录下,生成Dockerfile文件,并将下面内容复制进去。

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

通过上面Dockerfile构建的镜像,包含Python应用程序所需的所有依赖项,也包括Python本身。上面文件中每条指令的含义是:

  • Python3.4镜像为基础镜像;
  • 添加当前目录.到镜像中的/code路径;
  • /code设置为工作目录;
  • 安装Python的依赖项;
  • 设置容器的默认命令python app.py

4.在当前目录下创建一个名为requirements.txt的文件,用来配置安装Python的依赖项,将下面内容复制到文件。

flask
redis

5.通过Compose文件来定义服务。同样在当前目录下创建一个docker-compose.yml的文件,然后将下面的内容复制进去。

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

上面的Compose文件定义了两个服务,webredis。首先看web服务:

  • 使用从当前目录中的Dockerfile文件构建的镜像
  • 将容器上的公开端口5000转发到主机上的端口5000(Flask web服务器的默认端口是5000)

redis服务使用从Docker Hub镜像仓库拉取的公共Redis镜像。
6.使用Compose来创建和运行你的应用,在当前目录中使用命令docker-compose up。然后你就可以看到如下的执行内容:

Creating network "composetest_default" with the default driver
Building web
Step 1/5 : FROM python:3.4-alpine
3.4-alpine: Pulling from library/python
8e3ba11ec2a2: Already exists
2baa13bb50be: Pull complete
94819cf8c320: Pull complete
fd37974ce96d: Pull complete
b7202c933744: Pull complete
Digest: sha256:f8c20ce4b774b816f3108ac6a9f08161c94824ec3626a3f93baffa2d3fecd02f
Status: Downloaded newer image for python:3.4-alpine
 ---> 73266cf72156
Step 2/5 : ADD . /code
 ---> d2739ab8a928
Step 3/5 : WORKDIR /code
 ---> Running in 37ed62ac8c11
Removing intermediate container 37ed62ac8c11
 ---> 25f7a4fbb7fa
Step 4/5 : RUN pip install -r requirements.txt
 ---> Running in 6f69dca0e3d9
Collecting flask (from -r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/7f/e7/08578774ed4536d3242b14dacb4696386634607af824ea997202cd0edb4b/Flask-1.0.2-py2.py3-none-any.whl (91kB)
Collecting redis (from -r requirements.txt (line 2))
  Downloading https://files.pythonhosted.org/packages/3b/f6/7a76333cf0b9251ecf49efff635015171843d9b977e4ffcf59f9c4428052/redis-2.10.6-py2.py3-none-any.whl (64kB)
Collecting Werkzeug>=0.14 (from flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/20/c4/12e3e56473e52375aa29c4764e70d1b8f3efa6682bef8d0aae04fe335243/Werkzeug-0.14.1-py2.py3-none-any.whl (322kB)
Collecting click>=5.1 (from flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/34/c1/8806f99713ddb993c5366c362b2f908f18269f8d792aff1abfd700775a77/click-6.7-py2.py3-none-any.whl (71kB)
Collecting Jinja2>=2.10 (from flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/7f/ff/ae64bacdfc95f27a016a7bed8e8686763ba4d277a78ca76f32659220a731/Jinja2-2.10-py2.py3-none-any.whl (126kB)
Collecting itsdangerous>=0.24 (from flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/dc/b4/a60bcdba945c00f6d608d8975131ab3f25b22f2bcfe1dab221165194b2d4/itsdangerous-0.24.tar.gz (46kB)
Collecting MarkupSafe>=0.23 (from Jinja2>=2.10->flask->-r requirements.txt (line 1))
  Downloading https://files.pythonhosted.org/packages/4d/de/32d741db316d8fdb7680822dd37001ef7a448255de9699ab4bfcbdf4172b/MarkupSafe-1.0.tar.gz
Building wheels for collected packages: itsdangerous, MarkupSafe
  Running setup.py bdist_wheel for itsdangerous: started
  Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/2c/4a/61/5599631c1554768c6290b08c02c72d7317910374ca602ff1e5
  Running setup.py bdist_wheel for MarkupSafe: started
  Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/33/56/20/ebe49a5c612fffe1c5a632146b16596f9e64676768661e4e46
Successfully built itsdangerous MarkupSafe
Installing collected packages: Werkzeug, click, MarkupSafe, Jinja2, itsdangerous, flask, redis
Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2 itsdangerous-0.24 redis-2.10.6
Removing intermediate container 6f69dca0e3d9
 ---> b0fd1432440e
Step 5/5 : CMD ["python", "app.py"]
 ---> Running in 4efeccdd4edb
Removing intermediate container 4efeccdd4edb
 ---> ae811597b7e9
Successfully built ae811597b7e9
Successfully tagged composetest_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Pulling redis (redis:alpine)...
alpine: Pulling from library/redis
8e3ba11ec2a2: Already exists
baf0a0bb402f: Pull complete
3b0b05ea68b5: Pull complete
ba5ab541f6bf: Pull complete
cddd527d7b95: Pull complete
2ee1c014ab33: Pull complete
Digest: sha256:273023e79a025c089fbf1be0b41c99d68f064b80caf1fff069d2fa5d05a8d183
Status: Downloaded newer image for redis:alpine
Creating composetest_redis_1 ... done
Creating composetest_web_1   ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1  | 1:C 10 Sep 06:00:42.812 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 10 Sep 06:00:42.812 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 10 Sep 06:00:42.812 # 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 10 Sep 06:00:42.816 * Running mode=standalone, port=6379.
redis_1  | 1:M 10 Sep 06:00:42.817 # 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 10 Sep 06:00:42.817 # Server initialized
redis_1  | 1:M 10 Sep 06:00:42.817 # 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 10 Sep 06:00:42.818 # 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 10 Sep 06:00:42.818 * 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: 236-932-282

Compose将拉取Redis镜像,为你的代码构建镜像,并启动定义的服务。在这种情况下,代码在构建时被静态复制到镜像中。
假设你上面的服务是运行在111.1.2.3,那么你在你的浏览器中输入http://111.1.2.3:5000/,就可以在浏览器中看到Hello World! I have been seen 1 times.。刷新一下浏览器页面,就会变成Hello World! I have been seen 2 times.
如果你是在本地运行,输入http://localhost:5000,如果不起作用,可以试试http://0.0.0.0:5000。如果你在Mac或Windows上运行Docker,那么可以使用命令docker-machine ip MACHINE_VM获得你Docker主机的IP地址。接着在浏览器中打开http://获得的IP:5000
7.再切换到另一个终端窗口,输入命令docker image ls。该命令会列出本地的镜像,从列表中我们可以看到

REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
composetest_web         latest              e2c21aa48cc1        4 minutes ago       93.8MB
python                  3.4-alpine          84e6077c7ab6        7 days ago          82.5MB
redis                   alpine              9d8fa9aa0e5b        3 weeks ago         27.5MB

8.在第二个终端中输入命令docker-compose down来结束正在运行的服务,或者在原来的终端中键入CTRL+C来停止应用程序。
9.添加Compose文件以添加数据卷,重新编辑docker-compose.yml文件,为你的web服务添加数据卷。

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

新的卷将你主机上的项目目录(当前目录)安装到容器内的/code,允许你动态修改代码,而无需重建镜像。
10.重新构建和运行app,在你项目目录下,输入docker-compose up

Recreating composetest_web_1 ... 
Recreating composetest_web_1 ... done
Attaching to composetest_redis_1, composetest_web_1
redis_1  | 1:C 10 Sep 06:00:42.812 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 10 Sep 06:00:42.812 # Redis version=4.0.11, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 10 Sep 06:00:42.812 # 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 10 Sep 06:00:42.816 * Running mode=standalone, port=6379.
redis_1  | 1:M 10 Sep 06:00:42.817 # 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 10 Sep 06:00:42.817 # Server initialized
redis_1  | 1:M 10 Sep 06:00:42.817 # 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 10 Sep 06:00:42.818 # 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 10 Sep 06:00:42.818 * Ready to accept connections
redis_1  | 1:M 10 Sep 07:00:43.044 * 1 changes in 3600 seconds. Saving...
redis_1  | 1:M 10 Sep 07:00:43.045 * Background saving started by pid 14
redis_1  | 14:C 10 Sep 07:00:43.050 * DB saved on disk
redis_1  | 14:C 10 Sep 07:00:43.050 * RDB: 0 MB of memory used by copy-on-write
redis_1  | 1:M 10 Sep 07:00:43.145 * Background saving terminated with success
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: 236-932-282

在浏览器中刷新页面,可以看到以上次为基准,继续增加。

如果你的项目位于Users目录(cd ~)之外,那么你需要共享你正在使用的Dockerfile和卷的驱动或位置。如果得到运行时错误,指示未找到应用程序文件,拒绝数据卷的装入,或者服务无法启动,那么请尝试启用文件或驱动共享。在Windowsmac上,卷需要放在C:\Users(Windows上)或/Users(Mac)目录之外。
如果在比较旧的Windows操作系统上使用Oracle VirtualBox,则可能会遇到上面的问题。

由于现在应用程序使用卷安装到容器中,因此你可以更改其代码并立即查看更改的结果而无需重建镜像。
11.不要停止镜像,然后在另外一个控制窗口中,改变app.py文件的内容。将浏览器打印内容由Hello World!变为Hello from Docker!。保存后,在浏览器中刷新页面,就可以看到内容已经发生改变。

Hello from Docker! I have been seen 4 times.

12.如果你想在后台运行你的服务,通过传入参数-d($ docker-compose up -d)来实现。通过命令docker-compose ps查看当前正在运行的服务。

Name                      Command               State           Ports         
-------------------------------------------------------------------------------------
composetest_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp              
composetest_web_1     python app.py                    Up      0.0.0.0:5000->5000/tcp

docker-compose run命令允许你运行一次性命令,例如,要查看web服务可用的环境变量。

PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=4ba17b303aa5
TERM=xterm
LANG=C.UTF-8
GPG_KEY=97FC712E4C024BBEA48A61ED3A5CA953F73C700D
PYTHON_VERSION=3.4.9
PYTHON_PIP_VERSION=18.0
HOME=/root

注意:如果你使用docker-compose up -d来启动服务,那么你停止服务需要使用命令docker-compose stop
你可以使用down命令会完全删除容器,包括其中的卷等。使用参数--volumes($ docker-compose down --volumes)也可以删除Redis容器使用的数据卷。

Stopping composetest_web_1   ... done
Stopping composetest_redis_1 ... done
Removing composetest_web_run_1 ... done
Removing composetest_web_1     ... done
Removing composetest_redis_1   ... done
Removing network composetest_default

讲到这里,你应该已经了解了Compose如何工作的基本知识。

翻译原文:
https://docs.docker.com/compose/overview/

猜你喜欢

转载自blog.csdn.net/benben_2015/article/details/82592316