Doker和Compose 兼容性矩阵:

官方文档

docker 邮件客户端 docker-client_docker

提示:您可以使用此文件的扩展名为.yml或.yanl扩展名

文件结构说明

从上面的示例模板文件中可以看出,顶级的配置项有:

ersion 定义了版本信息
services 定义了服务的配置信息
networks 定义了网络信息,提供给 services 中的 具体容器使用
volumes 定义了卷信息,提供给 services 中的 具体容器使用

关于顶级services 配置参考

1.container_name

指定容器名称。默认将会使用项目名称_服务名称_序号 这样的格式。

1 | container_name: docker-web-container

示例

version: "3.8"
services:
  web5:
    image: nginx  
    container_name:  docker-web-container

注意: 指定容器名称后,该服务将无法进行扩展(scale),因为 Docker 不允许多个容器具有相同的名称。

2.labels

注意每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像。

如果使用 build 指令,那么在 Dockerfile 中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等)
将会自动被获取,无需在 docker-compose.yml 中再次设置。

下面分别介绍几个指令的用法:

3.build

指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对 docker-compose.yml 文件的路径)。 Compose 将会利用它自动构建这个镜像,然后使用这个镜像。
类似于命令行的 docker build .

version:"3"
services:
  webapp:
    build: .   #当前这个路径

示例:

1 | mkdir build
2 | cat Docker-compose.yml
 version:"3"
 services:
   webapp:
     build: .
3 | cat Dockerfile
  From nginx
  COPY ./index.html /usr/share/nginx/html/index.html 

4 | echo 哈哈哈哈哈 > index.html     # 内容只是为了显示效果
5 | docker-compose up -d            # 构建这个镜像

你也可以使用 context 指令指定 Dockerfile 所在文件夹的路径。

同时使用 dockerfile 指令指定 Dockerfile 文件名。

version: '3'
services:

  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate

4.image

指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。

1 | image: ubuntu 
2 | image: nginx:alpine
3 | image:  mysql/mysql-server:5.7

示例:

1 | mkdir image
2 | cd image/
3 | cat docker-compose.yml
version: "3.8"
services: 
   sky1:
     image: nginx   #  本地容器存在的镜像
 4 | docker-compose up -d

如果同时指定了 imagebuildimage 不在具有单独使用它的意义,而是指定了目前要构建的镜像的名称。 也就是说 Compose 会使用 build 指令中指定的 Dockerfilel 构建的镜像,之后构建的镜像名称使用 image 中指定的名字 webapp:tag命名。

1 | build: ./dir
2 | image: webapp:tag

示例:

1 | mkdir image
2 | cd image/
3 | cat Dockerfile
  FROM nginx  
4 | cat docker-compose.yml
version: "3.8"
services: 
   sky1:
     image: nginx   #  本地容器存在的镜像
   sky2:
     build: .
     image: webapp:1.0
 4 | docker-compose up -d

以上这个示例 构建的镜像是image设置的镜像名称!

5.command

使用command 可以覆盖容器启动后默认执行的命令

1 | command: bundle exec thin -p 3000

也可以写成类似Dockerfile中的格式

1 | command: [bundle, exec, thin, -p, 3000]

示例:

1 | mkdir command
2 | cd command/
3 | cat docker-compose.yml
version: "3"
services:
   app1:
     image:nginx
     command: /bin/sh
     container_name: nginx-sh
   app2:
     image: nginx
     container_name: nginx-off
 4 | docker run -d nginx /bin/sh  # 第一种方法运行
 5 | docker run -d nginx  # 第二种方法运行
 6 | docker-compose up -d # 启动docker-compose的yml文件

结果如图所示

docker 邮件客户端 docker-client_docker 邮件客户端_02

6.depends_on

解决容器的依赖、启动先后的问题。以下以下例子中会先启动容器 dbredis 再启动 web

version: '3'

services:
  web:
    build: .
    depends_on:
      - db
      - redis

  redis:
    image: redis

  db:
    image: postgres

注意: web服务不会等待redis 和db 【完全启动】 之后才启动
实质上规定的是启动容器的顺序,不会自动检测出
自己所依赖的容器是否真正启动完成

6.environment

设置环境变量。你可以使用数组或字典两种格式。

只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄露不必要的数据

environment:
  RACK_ENV: development
  SESSION_SECRET:

environment:
  - RACK_ENV=development
  - SESSION_SECRET

示例

1 | mkdir command
2 | cd command/
3 | cat docker-compose.yml
version: "3.8"
services:
  h2:
    image: alpine
    stdin_open: true
    tty: true
    environment:
       user: tao
       TEST:

在自己的服务器中,给TEST赋个值

1 | TEST=123456789
2 | echo $TEST
3 | docker-compose up -d
4 | docker-compose exec h2 sh   # 进入容器
5 |  echo $TEST #   这样会显示赋的值

在服务器主机上,声明TEST为环境变量

1 | export TEST
2 | docker-compose up -d

如果变量名称或者值中用到 true|false,yes|no 等表达 布尔 含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义。这些特定词汇,包括

y|Y|yes|Yes|YES|n|N|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF

7.expose

暴露端口,但不映射到宿主机,只被其他容器连接到此容器时使用。

仅可以指定容器内部的端口为参数

expose:
 - "3000"
 - "8000"

8.ports

映射端口信息
使用:
宿主端口: 容器端口(即: HOST:CONTAINER)的格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。

ports:
 - "3000"
 - "8000:8000"
 - "49100:22"
 - "127.0.0.1:8001:8001"

注意:当使用HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 YAML 会自动解析 xx:yy 这种数字格式为 60 进制。为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式。

示例

1 | mkdir ports
2 | cd ports
3 | cat doker-compose.yml
version: "3.8"
services:
  web2
    image: nginx
    ports:
      - "9000:80"   # docker run -p 9000:80
4 | docker-compose up -d

在主机上:直接测试

1 | curl 127.0.0.1:9000

9.extra_hosts

类似Docker中的 --add-host参数,指定额外的host 名称映射信息。

extra_hosts:
 - "googledns:8.8.8.8"
 - "dockerhub:52.1.157.61"

在启动后的服务容器中/etc/hosts文件中添加如下两条条目

1 | 8.8.8.8 googledns
2 | 2.1.157.61 dockerhub

示例

1 | mkdir extra_hosts
2 | cd extra_hosts
3 | cat docker-compose.yml
version: "3.8"
services:
  web2
    image: nginx
    ports:
      - "8500:80"
    extra_hosts:
      - "web3:192.168.64.5"
      - "www.taotao.com:192.168.64.55"
4 | docker-compose up -d
5 | docker-compose exec web2 sh(登录容器)
6 | cat /etc/hosts  (此命令会看到两个ip会添加在hosts文件中)

10.networks

要加入的网络,使用顶级networks 定义下的项目

services:
  some-service:
    networks:
     - some-network
     - other-network
networks:
  some-network:
  other-network:

示例

1 | mkdir network
2 | cd network/
3 | cat docker-compose.yml
version: "3.8"
services:
  web5:
    image: nginx
    ports:
      - "8530:80"
    networks: #自定义的网络名称
      - h5-net
  web4:
    image: centos
    tty: true
    stdin_open: true
    networks:
      - h5-net      #docker run --network=h5-net
networks:    #docker network create
  h5-net:
 4 | docker-compose up -d
 5 | docker network inspect network_h5-net  # 查看network里的web5和web4
 6 | docker-compose exec web4 bash
 7 | ping web4

案例:

docker 邮件客户端 docker-client_docker_03

1 | mkdir web-db-redis
2 | cd  web-db-redis/
3 | cat docker-compose.yml
version: "3.8"
services:
  web2:
    image: nginx
    networks:
      - net-web
      - net-db
  mysql:
    image:
    networks:
      - net-db
  redis:
    image: redis:alpine
    networks:
      - net-db
networks:
   net-db:
   net-web:

4 | docker-compose up -d
5 | docker-compose ps  # 查看容器
6 | docker-compose exec web2 sh   登录容器

10.1 指定IPv4IPv6

version: "2.4"

services:
  app:
    image: busybox
    command: ifconfig
    networks:
      app_net:
        ipv4_address: 172.16.238.10
        ipv6_address: 2001:3984:3989::10

networks:
  app_net:
    driver: bridge
    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
修改上方 的`docker-composversion: "2.4"

services:
  app:
    image: busybox
    command: ifconfig
    networks:
      app_net:
        ipv4_address: 172.16.238.10
        ipv6_address: 2001:3984:3989::10

networks:
  app_net:
    driver: bridge
    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

docker 邮件客户端 docker-client_nginx_04

指定自定义IPAM配置。这是一个具有多个属性的对象,每个属性都是可选的:
driver:自定义IPAM驱动程序,而不是默认驱动程序。 config:具有零个或多个配置块的列表,每个配置块包含以下任一键:
subnet:CIDR格式的子网, 就是这个网络的网段 ip_range:从中分配容器IP的IP范围
gateway:主子网的IPv4或IPv6网关
aux_addresses:网络驱动程序使用的辅助IPv4或IPv6地址,作为从主机名到IP的映射
options:特定于驱动程序的选项作为键值映射。

示例

1 | cat docker-compose.yml
version: "3.8"
services:
  web5:
    image: nginx   
# (nginx)这个镜像不支持 直接查看ip  需使用docker inspect 容器名
    tty: true
    stdin_open: true
    container_name: tao
    ports:
      - "8530:80"
    networks: #自定义的网络名称
      h5-net:
        ipv4_address: 172.16.238.10

  web4:
    image: centos
    tty: true
    stdin_open: true
    networks:
      - h5-net      #docker run --network=h5-net
networks:    #docker network create
  h5-net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.16.238.0/24
          gateway: 172.16.238.1
1 | docker-compose down   # 删除上面network创建的容器
2 | docker-compose up -d
3 | docker-compose exec web4 ip a  # 查看web4的ip
4 | docker inspect tao    #   查看web5 的ip

第二种方法:

1 | cat docker-compose.yml
vim docker-compose.yml
version: "3.8"
services:
  web5:
    image: centos   
# (centos)这个镜像支持 直接查看ip 
    tty: true
    stdin_open: true
    container_name: tao
    ports:
      - "8530:80"
    networks: #自定义的网络名称
      h5-net:
        ipv4_address: 172.16.238.10

  web4:
    image: centos
    tty: true
    stdin_open: true
    networks:
      - h5-net      #docker run --network=h5-net
networks:    #docker network create
  h5-net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.16.238.0/24
          gateway: 172.16.238.1
1 | docker-compose down
2 | docker-compose up -d
3 | docker-compose exec web5 ip a   # 这种是基于centos的镜像  才可以直接查看ip

10.2使用现有网络

如果您希望容器加入现有网络,请使用以下external选项

version: "3"
servers:
   host1:
      image: centos
      stdin_open: true
      tty: true
networks:
  # 此项目中的服务使用的默认网络,此网络不会被创建
  # 实际会使用 my-pre-existing-network
  default:
    external:
      name: my-pre-existing-network

这种情况下,Compose不会尝试创建名为 [projectname]_default 的网络,而是查找名为 my-pre-existing-network 的网络,并将应用程序的容器连接到该网络。

也可以把默认 default 网络改成其他的名称,比如

version: "3.8"
services:
   host1:
     image: centos
     stdin_open: true
     tty: true
     networks:
       shark:
networks:
     tao:
    external:
      name: my-pre-existing-network

示例:

1 | mkdir net-exnet
2 | cd net-exnet/
3 | cat docker-compose.yml
version: "3.8"
services:
   h2:
     image:centos
     stdin_open: true
     tty: true
networks:
  default:
    external:
      name: networks_h5-net
4 | docker-compose exec h2 bash   #  登录h2 这个容器
5 | ip a

11.aliases

网络上此服务的别名(备用主机名)。同一网络上的其他容器可以使用服务名称或此别名连接到其中一个服务的容器。

由于aliases是网络范围的,因此相同的服务可以在不同的网络上具有不同的别名。

一般格式如下所示。

services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2

示例

1 | mkdir aliases
2 | cd aliases
3 | cat docker-compose.yml
version: "3.8"
services:
   h2:
     image: centos
     stdin_open: true
     tty: true
     networks:
       n-1:
        aliases:
          - h1
       n-2:
        aliases:
          - hh
   h3:
     image: centos
     stdin_open: true
     networks:
       n-1:
   h4:
     image: centos
     stdin_open: true
     networks: 
       n-2:
networks:
  n-1:
  n-2:

4 | docker-compose exec h3 ping h2   别名ping

12.healthcheck

通过命令检查容器是否健康运行。

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"]
  interval: 1m30s
  timeout: 10s
  retries: 3

示例

1 | mkdir healthcheck
2 | cd healthcheck/
3 | cat docker-compose.yml
version: "3"
services:
  web1:
      image: nginx
      healthcheck:
        test: ["CMD", "curl", "-f", "http://localhost"]
        interval: 5s
        timeout: 3s
        retries: 3
4 | docker-compose up -d
5 | docker-compose ps

13.volumes

1.volumes
数据卷所挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)

该指令中路径支持相对路径。

volumes:
 - /var/lib/mysql
 - cache/:/tmp/cache
 - ~/configs:/etc/configs/:ro

卷的 bindvolume 的混合使用

version: "3.2"
services:
  web:
    image: nginx:alpine
    volumes:
      # 卷 (volume)
      - type: volume
        source: mydata
        target: /data
        volume:
          nocopy: true
      # 挂载 (bind)
      - type: bind
        source: ./static
        target: /opt/app/static

  db:
    image: postgres:latest
    volumes:
      - "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
      - "dbdata:/var/lib/postgresql/data"

volumes:
  mydata:
  dbdata:

示例 (这个直接修改网页是不及时生效的)

1 | mkdir volume
2 | cd volume/
3 | mkdir nginx
4 | mkdir -p nginx/conf
5 | echo haha > nginx/index.html
5 | cat docker-compose.yml

文件内容

version: "3.8"
services:
   web2:
   image: nginx
   volumes:
     - type: bind     # bind volume   tmpfile
       source: ./nginx/index.html
       target: /usr/share/nginx/html/index.html
     - type: bind 
       source: ./nginx/conf/default.conf
       target: /etc/nginx/conf.d/default.conf
1 | docker exec -it nginx sh   # 登录nginx容器   nginx镜像本地本地存在的!
2 | cd /etc/nginx/conf.d/      #将容器内的这个目录下的文件查看一下
3 | docker cp id:/etc/nginx/conf.d/default.conf .   #  这个id是nginx的镜像id,拷贝到当前目录下
4 | mv default.conf nginx/conf/
5 | docker-compose up -d
6 | curl 127.0.0.1:8090   # 这步是在容器内执行  查看
6 | docker-compose exec web2 curl localhost:8090   # 这个是在服务器上直接执行的  交互式

示例2:(这个直接修改网页是及时生效的)
在上面这个环境下执行 直接修改docker-compose.yml文件

1 | cat docker-compose.yml

文件内容如下

version: "3"
services:
  web2:
    image: nginx:alpine
    volumes:
      - type: bind     # bind volume   tmpfile
        source: ./nginx/
        target: /usr/share/nginx/html/
      - type: bind
        source: ./nginx/conf/default.conf
        target: /etc/nginx/conf.d/default.conf
1 | docker-compose exec web2 curl 127.0.0.1:8090  
 # 直接访问   同时也可以修改index.html文件继续执行此命令  然后持续观察页面结果

以目录的方式挂载

1 |  cat docker-compose.yml

文件内容如下

version: "3"
services:
  web2:
    image: nginx:alpine
    volumes:
      - type: bind     # bind volume   tmpfile
        source: ./nginx/
        target: /usr/share/nginx/html/
      - type: bind
        source: ./nginx/conf/
        target: /etc/nginx/conf.d/

停止容器,重新启动

1 | docker-compose down -v
2 | docker-compose up -d
3 | cd nginx/conf
4 | vim default.conf   # 修改端口
5 | docker-compose exec web2 sh  # 登录容器   
6 | cat etc/nginx/conf.d/default.conf  # 查看修改的内容是否同步
7 | docker-compose exec web2 curl localhost:8000  # 查看结果
8 | docker-compose down   # 重启启动  执行第7步操作去继续查看结果

14.sysctls+ulimits

sysctls

配置容器内核参数

sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0

ulimits

指定容器的ulimits限制值
例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制) 和 40000(系统硬限制,只能 root 用户提高)。

ulimits:
    nproc: 65535
    nofile:
      soft: 20000
      hard: 40000

综合示例

1 | mkdir ysctls-ulimit
2 | cd ysctls-ulimit
3 | cat docker-compose.yml

文件内容如下

version: "3"
services:
  web2:
    image: nginx
    sysctls:
      net.core.somaxconn: 1024
    ulimits:
      nproc: 65535
      nofile:
        soft: 20000
        hard: 40000

启动容器,进入容器,查看

1 | docker-compose up d
2 | docker-compose exec web2 bash
3 | ulimit -a