在之前的工作中,我一直使用docker run
命令,单独启动container,再加入overlay网络,以实现部署工作。这种方式看似直接,但是随着服务包含的container个数越来越多,docker命令也就越来越多,由此带来许多重复工作。
在官网上看到,docker-compose可以执行container编排(容器编排),尤其是compose file -v3版本加入了许多功能,可以方便地把服务中的container部署在单个docker节点或者多个swarm节点上。考虑到目前的使用情况,我们确实到了需要使用docker高级特性的阶段,所以进行实践。
分享一个示例:https://hackernoon.com/deploy-docker-compose-v3-to-swarm-mode-cluster-4159e9cca712#.lyx2e8fd9
上面的例子描述了,如何使用compose file v3和swarm,构建一个投票系统。与本文的区别:实例中运用了docker stack deploy
在多个docker swarm节点上部署应用服务;本文采用docker-compose up
,分别在两台docker节点上面部署应用容器。
1. 使用docker-compose,进行container编排
docker-compose是容器编排的利器,那么我们应该如何使用呢?
1.1 业务需求
我们的业务:在两台docker主机上,分别建立一组服务。简单起见,我把docker节点命名为nodeDB和nodeService。顾名思义,我们要在nodeDB上面建立database服务(部署oracle),在nodeService上部署应用容器。容器之间的跨主机通信就是通过swarm的overlay网络完成。
1.2 编写dockerfile
FROM 172.100.1.15:5000/oracle11g_server_v3
RUN mkdir /frs/
COPY /cafisFRSDB/ /frs/
COPY /cafisFRSDB/listener.ora /app/oracle/11.2.0/network/admin/
CMD ["/bin/bash", "/frs/startup.sh"]
dockerfile内容很简单,就是copy文件;CMD就是在启动container时,执行shell脚本(启动oracle服务和实例,实现业务逻辑)。
1.3 编写docker-compose.yml
version: '3'
services:
frs_orasvr:
build:
context: ./frsDB
dockerfile: Dockerfile
image: frs_orasvr_img:v1
container_name: frs_orasvr
hostname: frs_orasvr
ports:
- "1521:1521"
volumes:
- /DATA/compose_frs/frsDB/cafisFRSDB/:/frs
networks:
- qrtSwamComposeNet
networks:
qrtSwamComposeNet:
driver: overlay
注意几个内容:
networks: 在compose file v3中,docker允许通过networks关键字,定义一个基于 docker0网桥的subnet,然后把我们的服务加到这个subnet中,这样实现了服务之间的隔离。一旦不需要这组服务,我们可以通过命令
docker-compose down
卸载服务和对应的subnet,不会对其他服务造成影响。build: 通过build命令,我们可以指定加载哪个dockerfile。我们可以把base image定制为自己的image,这些定制化的步骤可以用dockerfile记录下来。docker image和dockerfile都可在开发人员之间共享。如果image过大不便其他人员pull拉取,我们可以共享dockerfile,使他人在本地构建image。
其他docker-compose文件指令可参见compose语法。
1.4 启动docker服务
现在我们到docker-compose.yml文件所在的目录,启动服务
# cd /parh/to/docker-compose.yml
# docker-compose up
# docker-compose ps // 检查服务是否启动
检查网络
# docker network ls
NETWORK ID NAME DRIVER SCOPE
p729h9nw2mxo composefrs_qrtSwamComposeNet overlay swarm
efd78e72a392 bridge bridge local
e08545f73ee1 docker_gwbridge bridge local
60fb66247b73 host host local
2th1f3svyriy ingress overlay swarm
1527c9d992e8 kj66be_net bridge local
c060dea57803 kj66interchange_default bridge local
c7d9e786b990 none null local
检查imge
# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
frs_orasvr_img v1 6e774eb7ee64 2 hours ago 207MB
<none> <none> e0f9577e8ef7 2 hours ago 207MB
compose运行image,生成container,并且调用shell脚本
# docker ps
伸缩容器
# docker-compose up --scale harbor-adminserver=2
// 需要指定对应容器的副本个数
到此,我们在nodeDB上面的工作就完成了。
1. 5 启动NodeService服务
NodeService的docker-compose.yml我们要在这个host (swarm node) 部署服务,服务中的container需要与之前node上面oracle服务通信。直接上code (简单起见,只列出了services 中的一个 container)
version: '3'
services:
frs_ftsoft:
build:
context: ./ftsoft
dockerfile: Dockerfile
image: frs_ftsoft_img:v1
networks:
- composefrs_qrtSwamComposeNet
container_name: frs_ftsoft
hostname: frs_ftsoft
mac_address: xx:xx:xx:xx:xx:xx
volumes:
- /data/CabisSvr/DockerFrs/ftsoft:/frs
networks:
composefrs_qrtSwamComposeNet:
external: true
Compose文件中使用的dockerfile内容与上个差不多,在这里就不多说了。
注意:
由于之前在nodeDB的compose file里已经创建了网络,我们这里需要指定为external:true (不需要在创建了),在container里面加入即可。
我们直接运行
docker-compose up
会报错,内容大致为找不到指定网络。这是由于之前在nodeDB上面创建的network不会自动在新的node上显示(官方说法),所以我们需要先在nodeService上面运行一个container,让其加入网络“composefrs_qrtSwamComposeNet”,例如:
# docker run -d --name=mybusybox --network=composefrs_qrtSwamComposeNet busybox /bin/sh
之后,我们便可以在nodeService上看到composefrs_qrtSwamComposeNet网络,此时再运行docker-compose up
就好了。
2. 使用docker swarm,进行stack编排
在nodeDB和nodeService节点上,通过运行两次docker-compose up
命令,我们实现了手动在不同的docker节点上运行容器。
用docker stack的方式部署nodeDB
# cd /path/to/docker-compose.yml
# docker stack deploy -c docker-compose.yml stack_name
# docker stack ls
# docker service ls
# docker service scale service_name=10
同理,对于nodeService使用相同的方法。
第二种方式最大好处是在多台docker swarm节点(swarm集群,不用关心应用容器在哪个docker swarm节点上,集群节点易于扩充)上完成部署(传说中的一键部署),最终服务以service端口映射宿主机端口的方式,展现给外部用户。
3. 参考文章
https://www.cnblogs.com/atuotuo/p/6588331.html
https://blog.csdn.net/pmlpml/article/details/53786575?locationNum=1&fps=1