docker compose 用于快速在集群中部署分布式应用。按我的理解也可以用于简化部署单个应用。譬如我要使用dock er启动一个nginx服务,需要做端口映射,挂载数据文件,指定镜像…等等,这种情况下,可以将启动容器的命令整合到docker-compose.yml文件中,可以在多个服务器上运行,瞬间就完成了nginx的安装及配置,再也不用去编译,解决环境依赖了,这种感觉实在是太爽了!!!
安装 #
- 使用pip
pip install docker-compose
- 从官方Github Release下载二进制包文件
- 其他方法略去
使用场景 #
在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
实战场景 #
需要部署的项目,只有两个docker容器,一个server,一个db。一般的部署方式是,分别启动两个容器,容器间通过互联的方式通信:
sudo docker run --rm -p 5433:5432 --name postgres -e POSTGRES_PASSWORD=minepwd -e POSTGRES_USER=mineusr -d postgres
sudo docker run --rm -p 9091:9091 --link postgres:postgres --name mineserver -d me/mineserver
这两条命令还是有挺麻烦的,如果记不住,当然可以用shell脚本来运行,可以如果其中某一个服务无法如期运行。。。就很监介了。这时候就可以引入docker-compose了。
编写docker-compose.yml来部署项目 #
version: "2" # 指定docker-compose版本
services: # 项目依赖的服务
postgres: # 服务名字
image: postgres # 服务需要的docker镜像与docker run命令中的镜像指定方式一致
volumes: # 挂载卷,这里的主要目的是,方便同步数据库和数据脚本
- ./postgres:/var/lib/postgresql/data
- ./sh:/usr/src/sh
ports: # 端口绑定
- 5433:5432
container_name: postgres
environment: # 设置环境变量
POSTGRES_PASSWORD: "minepwd"
POSTGRES_USER: "mineusr"
POSTGRES_DB: "minedb"
mineserver:
image: me/mineserver
volumes: # 挂载卷,方便查看输出日志
- ./logs:/usr/src/mineserver/logs
ports:
- 9091:9091
container_name: mineserver
links: # 容器互联
- postgres:postgres
在编写docker-compose.yml的时候,需要注意的是各个选项的数据类型,不过docker-compose会有提示,也很方便
这样编写之后,可以直接运行docker-compose up
就可以启动两个容器了。输出如下:
➜ mineserver git:(yeqown) docker-compose up
Starting postgres ... done
Starting mineserver ... done
Attaching to postgres, mineserver
mineserver | 2018/01/25 06:28:02 Loading config: ./configs/config.json
mineserver | 2018/01/25 06:28:02 init all logger done
mineserver | 2018/01/25 06:28:02 host=postgres user=mineusr dbname=minedb sslmode=disable password=minepwd
mineserver | panic: dial tcp 172.18.0.2:5432: getsockopt: connection refused
mineserver |
mineserver | goroutine 1 [running]:
mineserver | mineserver/vendor/app/models.ConnPgsql(0xc4200127d0, 0x4a)
mineserver | /go/src/mineserver/vendor/app/models/pgsql.go:17 +0x28b
mineserver | main.main()
mineserver | /go/src/mineserver/main.go:32 +0x16d
mineserver exited with code 2
postgres | 2018-01-25 06:28:05.360 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
postgres | 2018-01-25 06:28:05.360 UTC [1] LOG: listening on IPv6 address "::", port 5432
postgres | 2018-01-25 06:28:05.363 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres | 2018-01-25 06:28:05.449 UTC [20] LOG: database system was shut down at 2018-01-25 05:48:24 UTC
postgres | 2018-01-25 06:28:05.475 UTC [1] LOG: database system is ready to accept connections
如输出,使用过程中遇到一个问题,mineserver
依赖于postgre
,导致mineserver
无法正常启动。解决方案有:
1 重启minerserver,docker-compose start mineserver
2 改写mineserver链接数据库的部分,增加重试机制
3 分成多个docker-composr.yml,按依赖关系来分先后启动
4 添加依赖关系来控制启动顺序,新增depends_on选项如下:
# docker-compose.yml
...
mineserver:
...
depends_on: # 依赖关系
- postgres
links: # 容器互联
- postgres:postgres
但是,也没有办法知道被依赖的服务是不是启动成功了,所以在必须依赖的时候后还是会有问题
5 参见官网解决方案,增加一个wait-for-it.sh
。
docker-compose.yml 文件如下:
# docker-compose.yml
...
mineserver:
...
depends_on: # 依赖关系
- postgres
links: # 容器互联
- postgres:postgres
command: ["./wait-postgres.sh", "./mineserver"] # 结合wait-postgres.sh理解
wait-postgres.sh 文件如下:
#!/bin/sh
# wait-postgre.sh
host="postgres"
for i in $(seq 1 10)
do
nc -z $host 5432
if [[ $? -eq "" ]]; then
echo -n .
sleep 1
else
echo "Postgres is ready"
break
fi
done
# execute mineserver, $1 is command that start mineserver
$1
# how to use?
# command: ["./wait-postgres.sh", "./imetro-server"]
关于5th,需要注意的要注意wait-for-it.sh
, 需要放到服务镜像中去;要根据server镜像中的shell来指定sh,譬如说,我最开始使用的是bash,然而bash在alpine中并不存在……;另外wait-for-it.sh 需要可执行权限哦。
关于docker-compose.yml的其他命令 #
官方文档或者Docker入门到实践已经讲的很清楚了