一、前言
docker-compose 依赖于yml文件,默认为docker-compose.yml文件,通过yml文件,可以完成一系列的服务编排,指定服务间的依赖,网络,挂载卷等,因此有必要掌握compose配置文件
二、compose 配置文件介绍
YML文件是一种非标记语言,以数据为中心,使用空白,缩进,分行组织数据
基本原则
- 大小写敏感
- 使用缩进表示层级关系
- 禁止使用tab键,只能使用空格
- 缩进长度没有限制,只要元素对齐就表示同一层级
- 使用#表示注释
- 字符串可以不用引号标注
数据结构
- 对象
- 数组
- 值类型和字符串
三、compose 配置文件详解
1.version
指定compose文件的版本号, 有1,2,3个版本,目前最新的是3版本,1版本已经在慢慢弃用,建议使用最新版本,如下命令,指定3版本
version: "3"
2.services
根节点,编排的服务需要写在services下面,如下配置,在services下编排了web服务和nginx服务,web,nginx服务名称可自己定义
version: '3'
services:
web:
image: dev_tools_web
nginx:
image: my_nginx:v1
注意名称不能使用大写,如下配置有myWeb有大写
version: '3'
services:
myWeb:
image: dev_tools_web
nginx:
image: my_nginx:v1
运行时报如下错误
3.image
指定镜像的名称或镜像ID,先从本地镜像仓库中找,如果找到,使用本地镜像,如果找不到,则从中央仓库下载,如下配置均可以
image: dev_tools_web
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd
4.build
除了使用image指定镜像外,还可以通过Dockerfile文件,在up命令启动时执行构建,使用的构建标签就是build,它可以指定Dockerfile文件所在目录,compose可以通过Dockerfile文件生成镜像,然后通过该镜像启动容器服务
Dockerfile文件放在/home/ubuntu/dev_tools目录下,因此可以使用绝对路径
version: '3'
services:
web:
build: /home/ubuntu/dev_tools
也可以使用相对路径,只要能读到Dockerfile文件
build: ../dev_tools
5.context
除了在build中直接指定Dockerfile所在目录的路径外,还可以通过contest上下文,指定上下文后,可以基于指定的上下文找Dockerfile文件
version: '3'
services:
web:
build:
context: /home/ubuntu
dockerfile: ./dev_tools/Dockerfile
6.container_name
容器的默认名称是<项目名><服务名><序号>,如果需要指定容器名称,可以使用container_name,在如下配置中,指定容器的名称为my_web
version: '3'
services:
web:
image: dev_tools_web
container_name: my_web
通过docker-compose up -d
创建并启动容器后,再使用docker-compose ps -a
使用查看,发现容器名称已变成my_web
但是这样会有一个问题,由于容器名称是唯一的,指定容器名称后,就无法进行扩容,比如要把web服务扩容到5个节点,执行扩容命令 docker-compse scale web=5
,则出现如下错误
7.ports
指定容器的端口映射,是一个数组,使用HOST:CONTAINER格式,或者只是指定容器的端口,宿主机会随机映射端口,如下配置,指定了缩主机(8090)和容器(8081)的端口映射
version: '3'
services:
web:
image: dev_tools_web
ports:
- 8090:8081
还可以同时指定多个端口,如下配置均有效
ports:
- "3000"
- "8090:8081"
- "49100:22"
- "127.0.0.1:8001:8001"
注意:当使用HOST:CONTAINER格式来映射端口时,如果你使用的容器端口小于60你可能会得到错误得结果,因为YAML将会解析xx:yy这种数字格式为60进制。所以建议采用字符串格式
8.depends_on
如果服务需要依赖于其他服务,可以使用depends_on指定依赖关系,depends_on是一个数组,compose创建并启动一个服务时,会优先启动依赖的服务,如下配置,web服务依赖于redis和db,先启动redis和db后,才会启动web服务
version: '3'
services:
web:
image: dev_tools_web
ports:
- 8081:8081
depends_on:
- redis
- db
redis:
image: wodby/redis
ports:
- 6379:6379
db:
image: mysql
ports:
- 3306:3306
9.volumes
挂载一个目录或已存在的数据卷容器,可以使用[HOST:CONTAINER]或[HOST:CONTAINER:ro]这样的格式,对于后者来说,数据卷只读,这样可以保证宿主机的文件不被修改
compose的数据卷可以是相对路径,也可以是绝对路径,还可以是已存在的数据卷(但是容器挂载路径只能是绝对路径)
version: '3'
services:
web:
image: dev_tools_web
volumes:
# 只指定容器挂载目录,Docker会制动创建一个数据卷
- /app/logs
# 使用绝对路径挂载数据卷
- /app/data:/tmp/data:ro
# 以 Compose 配置文件为中心的相对路径作为数据卷挂载到容器
- ./cache:/tmp/cache
# 已经存在的数据卷
- file_data:/tmp/file_data
volumes:
file_data:
以上配置,使用docker-compose config
检查配置,结果如下
以上结果可看出,挂载目录./cache:/tmp/cache
和数据卷file_data
未指定操作权限,默认权限为rw
–可读可写;如果数据卷需要给其他服务共享,则需要定义在volumes
标签下,服务启动时,如果数据卷不存在,则先创建数据卷,如下启动结果
配置 - /app/logs
未指定数据卷,启动服务时,docker会自动创建一个数据卷,如下结果
配置 - /app/data:/tmp/data:ro
和 - ./cache:/tmp/cache
指定的是宿主机和容器的挂载目录,这种挂载目录只能容器内部使用
compose创建并启动容器时
- 在宿主机中:在根路径下会自动中创建app和data目录,在yml文件所在路径下创建cache目录
- 在容器中:自动在根路径下创建tmp目录及其data,cache,file_data子目录,使用命令
docker exec -it app_web_1 /bin/bash
进入到容器内部,发现根路径下多出tmp目录,并在tmp目录中有data,cache,file_data子目录
删除容器时,在容器启动时创建的数据卷并不会自动删除,需要使用docker volume rm [volume_name]
手动删除
10.networks
Docker提供的network功能能够对容器进行网络上的隔离,如下配置,我们创建了三个服务和两个网络,其中proxy和web共用frantnet网络,web和db共用endnet网络
version: '3'
services:
proxy:
image: nginx
networks:
- frantnet
web:
image: dev_tools_web
networks:
- frantnet
- endnet
db:
image: mysql
networks:
- endnet
networks:
frantnet:
endnet:
使用命令 docker-compose up -d
启动服务,从执行结果可看出,创建了两个网络和三个容器
使用docker network ls
可以查看到创建的网络
使用命令 docker exec -it app_web_1 /bin/bash
进入到容器app_web_1中检查容器的网络连接状态,
因为 we 服务同时连接到了 frantnet 和 endnet 两个网络中,所以它可以同时连接这两个网络中的其它容器(proxy 和 db),(注意,ping命令前需要在容器中通过 apt-get update && apt-get install iputils-ping
命令安装 ping 命令):
然后连接到app_proxy_1容器中,访问db服务,发现proxy中也可以访问到db,不是说存在网络隔离吗,怎么还能访问到呢,这是因为frantnet和endnet都是brigde,想要实现网络隔离,需要指定为overlay
networks:
endnet:
driver: overlay
frantnet:
driver: overlay
PS:要指定overlay,要求节点在swarm中