使用

通过实例,介绍docker-compose基本使用方法和YAML的常用书写形式。包括单主机的使用和swarm使用两部分。

单主机使用

下例中展示了一个docker-compose.yaml文件样例:

注意:docker-compose.yaml文件中一定要注意缩进格式,不注意的会容易出错。比如,下例中将container_nameservices一样,都靠最左边的话,就会出错。

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_test1compose_test2

对于compose_test1,指定了它的容器名称为compose_test1,使用的镜像为busybox。并将主机的目录/home/compose_test与容器的/root目录做了映射。

对于compose_test2,指定了它的容器名称为compose_test2,使用的镜像为busybox。同时compose_test2指定了commandifconfig,代替了默认的shvolumes_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_defaultdu_net_test(你的名称会有所不同)。这是因为compose_test1,没有定义网络信息,compose将会为compose_test1创建一个使用默认驱动的网络du_default,网络名称自动生成。compose_test2定义了网络为net_testnet_test为docker-compose.yaml文件最后部分,使用networks关键字创建的网络,指定了驱动为bridge,并使用ipv6,同时指定了ipv4和ipv6的子网和网关信息,compose根据这些信息创建了一个名称为du_net_test的网络(名称自动生成)。

compose_test2中使用ipv4_addressipv6_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_test1compose_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_test0compose_test1compose_test2compose_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)

出错。