docker-compose

概念

用来定义和管理多个容器的容器编排工具,docker-compose是docker-fig的升级版。
能做什么?
能够快速管理和创建多个容器,比如我直想起一个WordPress,在容器中也不需要自己去搭建lamp和然后安装WordPress了,只需要在docker hub找mysql和WordPress的镜像就可以,然后自己docker run,传对应的参数进去,映射端口,映射目录,很麻烦,同时非常容易出错,有了docker-compose,你只需要通过yaml语言,编写docker-compose脚本,然后就可以通过docker-compose一键是启动,关闭,删除这些容器了。脚本更加好维护和方便迁移。

安装docker-compose
可以直接通过pip 安装,因为docker-compose是基于python写的

1
pip install docker-compose

原理
dockerc-compose使用不同的请求将会调用不同的python方法去处理,比如使用docker-compose run -d将会调用run方法处理,最终调用docker-daemon去完成操作,docker-compose借助docker-py来完任务,docker-py是一个使用python开发并调用docker-daemon api的docker client包。

docker-compose命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
–-verbose:输出详细信息。
-f:制定一个非docker-compose.yml命名的yaml文件。
-p:设置一个项目名称,默认是当前目录的名称。
-d:表示后台运行
--project-directory :设置一个项目路径默认
build:构建镜像,docker-compose里面镜像来源有两种一种是通过Dockerfile构建,一种是通过镜像仓库pull下来,build在这里就是指调用Docker-compose的build参数,构建镜像
config:用于检查docker-compose的yml文件语法是否有错误
create:创建出来的容器状态为create状态。
down:将创建出来的容器集群down掉。
events:接收容器事件
exec:对run的容器执行命令
ps:输出正在运行容器
pull:pull一个服务镜像下来 docker-compose pull server_name
push:上传一个容器镜像 docker-compose push server_name
stop:停止容器集群
start:启动容器集群
up:创建和启动一个容器
scale:设置运行容器的数量,可以进行集群伸缩,如docker-compose scale resource_name=container_num


下面这个docker-compose.yml默认执行docker-compose up -d只会起一个web1一个db1,web1使用centos镜像,db1使用httpd镜像,并且db1依赖web1,必须等到web1安装完才能操作。

1
2
3
4
5
6
7
8
9
10
version: "3"
services:
web1:
image: centos
tty: true
db1:
image: httpd
depends_on:
- web1
tty: true

假设web1资源不够了需要进行扩容到5个
执行

1
docker-compose scale web1=5

迅速扩容到5个,此时高峰期以过,不需要这么多web1容器了需要缩减到正常
执行

1
docker-compose scale web1=1

docker-compose.yml语法解析

详细参考

1
2
https://docs.docker.com/compose/compose-file/compose-versioning/
https://www.cnblogs.com/freefei/p/5311294.html

1
2
3
4
5
6
7
8
9
10
11
以下面这个文件为例
version: "3"
services:
web1:
image: centos
tty: true
db1:
image: centos
depends_on:
- web1
tty: true

version :版本,docker-compose的版本,不同的版本所支持的语法是不一样的,所对应的docker版本也是不一样的
如,但新版本都是向下兼容的 。

services:表示定义服务,是以容器为颗粒度的。
web1:表示服务名。
image:才用哪个镜像,docker-compose支持两种镜像来源,一种是从docker-hub上,或本地镜像仓库,一种是通过dockerfile构建镜像那这里就应该是build了。
tty:根docker run的-t一样,为容器重新分配一个伪输入终端。
depends_on:依赖那个服务,这里表示等待哪个服务先完成,在进行本服务的操作。

其中参数

1
2
3
links:
- server_name
- server_name:alias_name

链接到其他服务中的容器,使用服务名称,或别名,这样在容器中就可以通过服务名的方式联通。但在新版本docker 17.09版本中发现就算不link,docker默认也将他们信息添加到docker dns中了可以直接ping通。

1
2
external_links
- container_name

链接外部已经存在容器,非docker-compose管理的容器

1
2
ports:
- "xxx:xxx"

端口映射

1
2
3
volumes:
-/dxx/xxx:/xxx
-/dxx/xxxx:xxx:ro

卷映射,加上ro表示只读模式。

1
2
volume_from:
- container_name

从另外一个服务或容器挂载他的卷。

1
2
3
environment:
- XXXX=XXX
- XXXX=XXX

设置环境变量

1
2
extra_hosts:
- "www.test.com: xxx.xxx.xxx.xx"

添加此项到hosts文件

container_name: xxx 设置容器名

hostname: xxx 设置主机名

restart:always 根docker run参数一样,无论怎么样,自动拉起此容器

例子

python flask框架网站

以docker官网例子docker-compose构建一个简单的动态网站为例
创建compose文件夹,并cd到目录

1
mkdir /compose

1
cd /compose

编写一个python文件,内容如下
vim app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
return 'Hello World! I have been seen {} times.\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)

其中host的redis为docker-compose里面定义的redis的service-name,因为新版本docker默认会将service_name 添加到dns所以可以不用link直接就可以通过主机名进行通信。

创建requirements.txt文件用于pip程序安装

vim requirements.txt

1
2
flask
redis

创建Dockerfile文件用于构建镜像
vim Dockerfile

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

创建Docker-compose文件,用于构建应用集群
vim docker-compose.yml

1
2
3
4
5
6
7
8
9
10
version: '3'
services:
web:
build: .
volumes:
- .:/code
ports:
- "5000:5000"
redis:
image: "redis:alpine"

开始运行
docker-compose up

访问浏览器http://localhost:5000,刷新一下times根着变一次。

查看容器

1
docker ps -a

如果要后台运行

1
docker-compose up -d

查看服务的环境变量

通过service_name控制单个服务的开关。

需要注意的是,如果没指定网络的话,默认docker-compose会创建一个以docker-compose.yml所在文件夹名为名的bridge网络。比如我的docker-compose.yml文件是放在zabbix这个目录,那么通过docker-compose构建集群后,会自动创建一个zabbix_default网络,类型为bridge。

如果需要使创建的应用集群同时创建网络,使用下面例子,创建docker集群时,同时构建指定网络名称和类型、网段的docker网络。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
networks:
- test
redis:
networks:
- test
image: "redis:alpine"
networks:
test:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.28.0.0/16

web和reids服务都通过network参数加入到test网络中,下面networks资源开始创建test网络,类型为bridge,ipadm驱动为默认,网段为172.28.0.0/16。

docker-compose默认没指定网络会创建一个自己的网络,然后将这些service加入进去。

执行docker-compose up -d

查看这个网络

如果需要加入一个已经存在的网络
创建网络

1
docker network create --driver bridge --subnet 192.168.1.0/24 --gateway 192.168.1.1 my_net

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
version: "3"
services:
web1:
image: centos
tty: true
networks:
- my_net
db1:
image: centos
depends_on:
- web1
tty: true
networks:
- my_net
networks:
my_net:
external: true
1
docker-compose up -d

在去镜像内查看就发现是192.168.1.0/24的网段了。

构建WordPress应用

使用两个镜像,一个mysql,一个WordPress,WordPress已经部署好了apache和php和WordPress。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: '3'
services:
db1:
image: mysql:5.7
volumes:
- /var/lib/mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress
wordpress:
image: wordpress:latest
depends_on:
- db1
ports:
- 8000:80
environment:
- WORDPRESS_DB_HOST=db1
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress
- WORDPRESS_DB_NAME=wordpress

默认docker-compose出来的容器已经自动添加service_name和ip的映射了,所以这里DB_HOST直接写db1,不用links也是可以的互通的。
这些镜像的环境变量可以在docker hub上找到

构建
使用下面的命令,所有的服务将使用后台模式被启动

1
docker-compose up -d

访问
http://localhost:8000

构建zabbix监控

zabbix-server分为两个部分,zabbix-server-mysql负责接收zabbix-agent的监控数据,然后将监控数据存储到mysql中,zabbix-web-nginx-mysql负责展示监控数据。

因为默认mysql数据库不是utf-8的编码所以需要重新构建下镜像
vim Dockerfile

1
2
FROM mysql:5.7
CMD ["mysqld", "--character-set-server=utf8", "--collation-server=utf8_bin"],

所以在mysql镜像这里没有直接用仓库的镜像,而是采用dockerfile重新构建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
version: '3'
services:
db1:
build: .
volumes:
- /var/lib/mysql:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_USER=zabbix
- MYSQL_PASSWORD=zabbix
- MYSQL_DATABASE=zabbix
zabbix-server:
image: zabbix/zabbix-server-mysql:ubuntu-3.4.4
ports:
- 10051:10051
volumes:
- /var/lib/mysql:/var/lib/mysql
environment:
- DB_SERVER_HOST=db1
- MYSQL_USER=zabbix
- MYSQL_PASSWORD=zabbix
- MYSQL_DATABASE=zabbix
zabbix-nginx-mysql:
image: zabbix/zabbix-web-nginx-mysql:ubuntu-3.4.4
depends_on:
- db1
ports:
- 8000:80
environment:
- DB_SERVER_HOST=db1
- MYSQL_USER=zabbix
- MYSQL_PASSWORD=zabbix
- ZBX_SERVER_HOST=zabbix-server
- PHP_TZ:Asia/Shanghai

启动
docker-compose up -d
访问
http://localhost:8000

参考链接
http://wiki.jikexueyuan.com/project/docker-technology-and-combat/yaml_file.html
https://www.hi-linux.com/posts/12554.html
https://docs.docker.com/compose/install/#install-compose
http://www.ywnds.com/?p=7592