使用
通过实例,介绍docker-compose基本使用方法和YAML的常用书写形式。包括单主机的使用和swarm使用两部分。
单主机使用
下例中展示了一个docker-compose.yaml文件样例:
注意:docker-compose.yaml文件中一定要注意缩进格式,不注意的会容易出错。比如,下例中将
container_name
与services
一样,都靠最左边的话,就会出错。
version: '2'
services:
compose_test1:
container_name: compose_test1
image: busybox
command: sh -c "while true; do echo compose_test1_hello; sleep 2; done"
volumes:
- /home/compose_test:/root
compose_test2:
container_name: compose_test2
image: busybox
command: sh -c "while true; do echo compose_test2_hello; sleep 2; done"
volumes_from:
- compose_test1
ports:
- "4000:4000"
- "${TEST1_PORT}:8000"
environment:
- COMPOSE_TEST2=test
networks:
net_test:
ipv4_address: 172.16.238.10
ipv6_address: 2001:3984:3989::10
networks:
net_test:
driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "true"
ipam:
driver: default
config:
- subnet: 172.16.238.0/24
gateway: 172.16.238.1
- subnet: 2001:3984:3989::/64
gateway: 2001:3984:3989::1
文件中包含了两个services
:compose_test1
和compose_test2
。
对于compose_test1
,指定了它的容器名称为compose_test1
,使用的镜像为busybox
。并将主机的目录/home/compose_test
与容器的/root
目录做了映射。
对于compose_test2
,指定了它的容器名称为compose_test2
,使用的镜像为busybox
。同时compose_test2
指定了command
为ifconfig
,代替了默认的sh
。volumes_from
指定了使用compose_test1
的挂载卷,即,将主机的/home/compose_test
目录同时也挂载到compose_test2
容器的/root
目录下。
compose_test2
指定了端口映射,将容器的4001
端口映射到主机4000
端口上,其他应用可通过主机的4000
端口与compose_test2
进行通信。同时将容器的8000
映射到主机的端口${TEST1_PORT}
上,${TEST1_PORT}
是主机的环境变量,如果没有设置该环境变量,在使用docke-compose up
命令创建和启动容器时,将会出现以下错误:
WARNING: The TEST1_PORT variable is not set. Defaulting to a blank string.
ERROR: Validation failed in file './docker-compose.yaml', reason(s):
services.compose_test2.ports is invalid: Invalid port ":8000", should be [[remote_ip:]remote_port[-remote_port]:]port[/protocol]
我们需要在主机上设置TEST1_PORT环境变量:
$TEST1_PORT=8000
$export TEST1_PORT
继续使用docke-compose up
命令创建和启动容器,将正常执行:
$./docker-compose up
Creating network "du_default" with the default driver
Creating network "du_net_test" with driver "bridge"
Creating ce
Creating compose_test2
Attaching to ce, compose_test2
ce | compose_test1_hello
ce | compose_test1_hello
compose_test2 | compose_test2_hello
ce | compose_test1_hello
compose_test2 | compose_test2_hello
ce | compose_test1_hello
compose_test2 | compose_test2_hello
ce | compose_test1_hello
compose_test2 | compose_test2_hello
从执行的日志中可以看到,compose创建了两个网络du_default
和du_net_test
(你的名称会有所不同)。这是因为compose_test1
,没有定义网络信息,compose将会为compose_test1
创建一个使用默认驱动的网络du_default
,网络名称自动生成。compose_test2
定义了网络为net_test
,net_test
为docker-compose.yaml文件最后部分,使用networks
关键字创建的网络,指定了驱动为bridge
,并使用ipv6,同时指定了ipv4和ipv6的子网和网关信息,compose根据这些信息创建了一个名称为du_net_test
的网络(名称自动生成)。
compose_test2中使用ipv4_address
和ipv6_address
关键字指定了ip地址,我们可以通过命令:
$docker inspect compose_test2
查看容器的网络信息:
"Networks": {
"du_net_test": {
"IPAMConfig": {
"IPv4Address": "172.16.238.10",
"IPv6Address": "2001:3984:3989::10"
},
接下来,我们看看挂载卷的情况。
使用docker exec
命令进入容器compose_test1
,并在容器中的/root目录下创建一个compose_test1目录
$docker exec -it compose_test1 sh
/ # mkdir /root/compose_test1
/ # ls /root/
compose_tes1
我们看一下主机的/home/compose_test目录下,此时也有compose_test1目录
$ls /home/compose_test/
compose_test1
同样的方法在compose_tes2
容器中的/root目录下创建一个compose_tes2目录,在主机的/home/compose_test目录下也能看到。
容器compose_tes2
,设置了环境变量:
COMPOSE_TEST2=test
进入容器compose_tes2
,并查看其环境变量:
$docker exec -it compose_test2 sh
/ # env
COMPOSE_TEST2=test
HOSTNAME=08c837d6e7cf
SHLVL=1
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
可看到环境变量COMPOSE_TEST1已成功设置。
使用docker-compose down
命令停止并删除容器:
./docker-compose down
Stopping compose_test2 ... done
Stopping compose_test1 ... done
Removing compose_test2 ... done
Removing compose_test1 ... done
Removing network du_default
Removing network du_net_test
可看到,容器compose_test1
和compose_test2
全部停止并被删除,同时compose生成的网络也被删除。
SWARM使用
有关SWARM的部署,本节不再叙述,请参见相关章节。 假设,有一个swarm集群,包含三个主机,IP地址如下:
docker70:192.168.48.70
docker71:192.168.48.71
docker72:192.168.48.72
swarm集群的管理节点为192.168.48.70:4000
。
编写docker-compose.yaml如下:
version: '2'
services:
compose_test0:
container_name: compose_test0
image: busybox
command: sh -c "while true; do echo compose_test1_hello; sleep 2; done"
network_mode: "bridge"
volumes:
- /home/compose_test:/root
environment:
- "constraint:node==docker70"
compose_test1:
container_name: compose_test1
image: busybox
command: sh -c "while true; do echo compose_test1_hello; sleep 2; done"
volumes_from:
- compose_test0
ports:
- "4001:4000"
environment:
- COMPOSE_TEST1=test1
network_mode: "bridge"
compose_test2:
container_name: compose_test2
image: busybox
command: sh -c "while true; do echo compose_test2_hello; sleep 2; done"
ports:
- "4002:4000"
environment:
- COMPOSE_TEST2=test2
- "constraint:node==docker71"
network_mode: "bridge"
compose_test3:
container_name: compose_test3
image: busybox
command: sh -c "while true; do echo compose_test3_hello; sleep 2; done"
ports:
- "4003:4000"
environment:
- COMPOSE_TEST3=test3
- "constraint:node==docker72"
network_mode: "bridge"
文件中包含四个容器:compose_test0
、compose_test1
、compose_test2
、compose_test3
。通过环境变量可设置每个容器运行在哪个节点;
environment:
- "constraint:node==docker71"
本例中,compose_test0
运行在docker70,compose_test2
运行在docker71,compose_test3
运行在docker72。
容器compose_test1
使用了:
volumes_from:
- compose_test0
容器compose_test1
将与compose_test0
运行在同一个节点,即docker70上。
创建并运行容器:
$./docker-compose -H 192.168.48.70:4000 up
Creating compose_test0
Creating compose_test2
Creating compose_test3
Creating compose_test1
Attaching to compose_test0, compose_test3, compose_test1, compose_test2
compose_test0 | compose_test1_hello
compose_test3 | compose_test3_hello
compose_test1 | compose_test1_hello
compose_test2 | compose_test2_hello
compose_test0 | compose_test1_hello
compose_test3 | compose_test3_hello
各个容器将在对应的节点上创建和运行。
使用docker-compose将容器运行在swarm上,必须为每个容器指定网络,不然会出现错误。比如,将docker-compose.yaml文件中的第八行注释掉:
#network_mode: "bridge"
然后启动容器:
$./docker-compose -H 192.168.48.70:4000 up
Creating network "test_default" with the default driver
ERROR: 500 Internal Server Error: failed to parse pool request for address space "GlobalDefault" pool "" subpool "": cannot find address space GlobalDefault (most likely the backing datastore
is not configured)
出错。