本文从本人博客搬运,原文格式更加美观,可以移步原文阅读:docker-compose容器编排
基本介绍
docker-compose
是docker官方的开源项目,负责实现对docker容器集群的快速编排。它的作用是定义和运行多个docker容器的应用
之前我们如果要启动多个容器,只能手动执行多个docker run
命令。然而在日常工作中,一个项目往往要同时启动非常多的容器,并且容器的启动顺序也有要求,例如要运行一个web项目,除了启动web服务容器之外,还需要启动它依赖的mysql、redis等等,这时候手动一个个启动非常麻烦
docker-compose
允许用户通过一个单独的docker-compose.yml
模板文件来定义一组相关联的应用容器为一个项目,它有2个重要的概念:
服务(service)
:一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。在docker-compose.yml
中定义项目(project)
:由一组关联的应用容器组成的一个完整业务单元,一个docker-compose.yml
文件就代表一个项目
docker-compose
的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。比如我们要开发一个Web项目,除了运行后端应用接口的容器,还需要依赖MySQL、Redis、RabbitMQ、Nginx等容器,那么就可以通过一个docker-compose.yml
来统一编排管理这一组容器
安装
1.linux
从官方下载编译好的docker-compose
二进制可执行文件,下载地址为:https://github.com/docker/compose/releases
下载完成后手动上传到linux指定目录/usr/local/bin
,将其文件名修改成docker-compose
。然后给其加上可执行权限
# 因为下载后的docker-compose文件是一个可执行脚本,所以要开放其权限
chmod +x /usr/local/bin/docker-compose
安装完成后可以用docker-compose -v
检查安装是否成功
2.win/mac
win/mac平台安装docker后就自带docker-compose
,可以直接使用
具体使用
1.入门
使用docker-compose
的基本步骤如下:
- 编写
docker-compose.yml
模板文件,指定要编排运行的一组容器 - 利用
docker-compose
指令启动模板文件中的所有容器
我们来尝试启动2个tomcat,编写如下的docker-compose.yml
version: "3.2" # 指定compose的版本
services:
tomcat1: # 代表一个容器的服务名称,在文件中必须唯一
image: tomcat:8.0-jre8 # 指定用哪个镜像来创建这个容器
ports:
- "8080:8080" # 指定容器与宿主机的端口映射
tomcat2:
image: tomcat:8.0-jre8
ports:
- "8081:8080"
把上述模板文件在独立的一个目录中创建,这里是/docker/compose
。然后在该目录下启动模板文件中定义的容器
docker-compose up
可以发现启动时,由于镜像不存在,compose先帮我们自动下载了镜像,然后启动2个tomcat容器,并且2个容器的日志颜色会进行区分
2.模板文件指令详解
模板文件指令指的是docker-compose.yml
中可以写的指令。每个指令都可以类比为docker run
中的某个参数
2.1 version
指的是docker compose
的版本号,与docker的版本有对应关系:
Compose file format | Docker Engine release |
---|---|
Compose specification | 19.03.0+ |
3.8 | 19.03.0+ |
3.7 | 18.06.0+ |
3.6 | 18.02.0+ |
3.5 | 17.12.0+ |
3.4 | 17.09.0+ |
3.3 | 17.06.0+ |
3.2 | 17.04.0+ |
3.1 | 1.13.1+ |
3.0 | 1.13.0+ |
2.4 | 17.12.0+ |
2.3 | 17.06.0+ |
2.2 | 1.13.0+ |
2.1 | 1.12.0+ |
2.0 | 1.10.0+ |
1.0 | 1.9.1.+ |
2.2 image
指定运行容器的镜像名称或id,如果本地镜像不存在,compose将会尝试拉取这个镜像
2.3 ports
容器与宿主机的端口映射信息,格式为宿主机端口:容器端口
,可以不指定宿主机端口,此时宿主机将会随机选择端口
version: "3.2"
services:
mytomcat:
image: tomcat:8.0-jre8
ports:
- "8081:8080"
- "8082:8082"
建议端口映射信息加上双引号,否则可能会出现一些意外错误
2.4 volumes
容器与宿主机的数据卷映射。可以采用如下格式:
宿主机绝对路径:容器绝对路径
数据卷名称:容器绝对路径
,如果采用这种方式,还必须在后面声明所使用的数据卷
version: "3.2"
services:
mytomcat:
image: tomcat:8.0-jre8
ports:
- "8080:8080"
volumes:
- tomcatwebapp:/usr/local/tomcat/webapps # 数据卷映射,如果采用数据卷名称方式,必须在下面定义数据卷名称
volumes:
tomcatwebapp: # 声明上面所使用的数据卷
如果使用数据卷名称方式进行映射,那么在启动容器时,compose会自动帮我们创建一个数据卷,名称为项目名_自定义数据卷名
,其中项目名为docker-compose.yml
模板文件所在的目录名
如果不想使用compose帮我们自动创建的这个带项目名前缀的数据卷名称,可以指定使用外部已存在的数据卷名称,但此时必须先用docker volume create
创建出指定的数据卷,否则会报错
version: "3.2"
services:
mytomcat:
image: tomcat:8.0-jre8
ports:
- "8080:8080"
volumes:
- tomcatwebapp:/usr/local/tomcat/webapps # 数据卷映射,如果采用数据卷名称方式,必须在下面定义数据卷名称
volumes:
tomcatwebapp: # 声明上面所使用的数据卷
external:
true # 使用外部已存在的数据卷tomcatwebapp,该数据卷必须存在,不存在的话必须先手动创建,否则报错
一般情况下使用compose默认帮我们创建的带项目名称前缀的数据卷即可,因为compose管理容器的单位是项目,这样能区分不同的项目
2.5 networks
配置容器使用哪个网络(桥)
version: "3.2"
services:
mytomcat:
image: tomcat:8.0-jre8
ports:
- "8080:8080"
networks:
- mynetwork # 指定容器连接哪个网络。指定的自定义网络名称必须在下面定义
networks:
mynetwork: # 定义网络。定义后才能在上面使用,否则报错
启动容器后,compose会自动帮我们创建mynetwork
网络
可以看出:
- 如果我们在模板文件中没有指定容器用的网络,那么compose会自动创建一个名称为
项目名_default
的网络,其中项目名为docker-compose.yml
模板文件所在的目录名 - 如果我们在模板文件中指定了容器的网络,那么compose会自动创建一个名称为
项目名_自定义网络名
的网络,其中项目名为docker-compose.yml
模板文件所在的目录名
如果我们不想让compose创建网络时名称前面带项目名的前缀,那么可以指定使用外部已存在的网络,但此时必须现用docker network create
创建出指定的网络,否则会报错
version: "3.2"
services:
mytomcat:
image: tomcat:8.0-jre8
ports:
- "8080:8080"
networks:
- mynetwork # 指定容器连接哪个网络。指定的自定义网络名称必须在下面定义
networks:
mynetwork: # 定义网络。定义后才能在上面使用,否则报错
external:
true # 使用外部已存在的网络mynetwork,该网络必须存在,不存在的话必须先手动创建,否则报错
一般情况下使用compose默认帮我们创建的带项目名称前缀的网络即可,因为compose管理容器的单位是项目,这样能区分不同的项目
2.6 container_name
指定容器的名称。不指定时默认由compose生成带项目名称前缀的容器名
version: "3.2"
services:
mytomcat:
container_name: tomcat01 # 指定容器的名称
image: tomcat:8.0-jre8
ports:
- "8080:8080"
2.7 environment
设置环境变量,可以使用数组或字典两种格式。如果只给定变量名称,不指定值的话会自动获取运行compose宿主机上对应的环境变量的值,可以用来防止泄露不必要的数据
version: "3.2"
services:
mysql5:
container_name: mysql01 # 指定容器的名称
image: mysql:5.7
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root # 等价写法MYSQL_ROOT_PASSWORD: root
如果环境变量的名称或值中用到
true|false
或者yes|no
这样的布尔表达式,建议放到引号里,避免解析错误
2.8 env_file
从文件中获取环境变量,可以为单独的文件路径或列表
如果通过docker-compose -f FILE
方式来指定compose.yml模板文件,则env_file
中变量的路径会基于模板文件路径
如果有变量名称与environment
指令冲突,则以后者为准
# 指定单个环境变量文件
env_file: .env
# 指定多个环境变量文件
env_file:
- ./common.env
- /opt/secrets.env
环境变量文件中每一行必须符合格式,支持#
开头的注释行
# mysql密码
MYSQL_ROOT_PASSWORD=root
一般我们会把一些敏感信息环境变量放到文件中,比如mysql密码。这样compose模板文件中不会暴露密码
2.9 command
用于run镜像之后覆盖容器启动时的默认命令,比如启动redis时docker run -p 6379:6379 -d --name redis5 -v redis.data:/data -v redis.conf:/etc/redis/redis.conf redis:5 redis-server /etc/redis/redis.conf
,需要如下配置
version: "3.2"
services:
redis5:
container_name: redis5 # 指定容器的名称
image: redis:5
ports:
- "6379:6379"
volumes:
- redis.data:/data
- redis.conf:/etc/redis
command: "redis-server /etc/redis/redis.conf" # 指定容器启动时要运行的命令
2.10 depends_on
解决容器之间的依赖、启动先后问题。比如我们自己的web应用会连接mysql、redis,那么就要求mysql、redis先启动,web应用后启动
version: "3.2"
services:
web:
image: mywebapp:latest
ports:
- "8080:8080"
depends_on: # 依赖于redis5和mysql5.7,会先启动redis5和mysql5.7
- redis5 # 注意一定要写services下面配置的服务id,而不是容器名称
- mysql5.7
redis5:
container_name: redis01
image: redis:5
ports:
- "6379:6379"
volumes:
- redis.data:/data
- /dockermapping/redis/conf/redis.conf:/etc/redis/redis.conf
command: "redis-server /etc/redis/redis.conf" # 指定容器启动时要运行的命令
mysql5.7:
container_name: mysql01
image: mysql:5.7
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root
2.11 build
如果要将我们自己的应用放到compose模板文件中进行编排,首先要用dockerfile生成镜像,然后在compose模板中编排,这样做稍显麻烦。build指令可以一步到位,在compose模板中将指定的dockerfile打包成镜像后再运行
version: "3.2"
services:
web:
build: # 启动服务时先将build命令中指定的dockerfile打包成镜像,再运行该镜像
context: myweb # 指定上下文目录,即dockerfile所在目录
dockerfile: Dockerfile # 指定dockerfile的文件名
ports:
- "8080:8080"
depends_on: # 依赖于redis5和mysql5.7,会先启动redis5和mysql5.7
- redis5 # 注意一定要写services下面配置的服务id,而不是容器名称
- mysql5.7
redis5:
container_name: redis01
image: redis:5
ports:
- "6379:6379"
volumes:
- redis.data:/data
- redis.conf:/etc/redis
command: "redis-server /etc/redis/redis.conf" # 指定容器启动时要运行的命令
mysql5.7:
container_name: mysql01
image: mysql:5.7
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root
2.12 限制容器可用内存
version: "3.2"
services:
redis:
image: redis:alpine
container_name: testredis
deploy:
resources:
limits:
memory: 2G # 限制容器可用最大内存为2G
3.docker-compose常用命令
对于docker-compose
来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器。如果没有特别的说明,命令的对象将是项目,这意味着项目中所有的服务都会收到命令影响
执行docker-compose [具体命令] --help
或者docker-compose help [具体命令]
可以查看某个具体命令的格式。docker-compose
的基本格式如下:
docker-compose [-f=<arg>...] [options] [COMMAND] [ARGS...]
命令的选项如下:
-f,--file FILE
:指定使用的compose模板配置文件,默认为docker-compose.yml
,可以多次指定-p,--project-name NAME
:指定项目名称,默认将使用模板文件所在目录名称作为项目名称--x-networking
:使用docker的可拔插网络后端特性--x-network-driver DRIVER
:指定网络后端的驱动,默认为bridge
--verbose
:输出更多调试信息-v,--version
:打印版本并退出
3.1 up
格式为docker-compose up [options] [SERVICE...]
- 该命令十分强大,它将尝试自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作。可以说大部分的时候都可以直接通过该命令来启动一个项目
- 连接的服务将会被自动启动,除非已经处于运行状态
- 默认情况下,
docker-compose up
启动的容器都在前台,控制台将会同时打印所有容器的输出信息,方便进行调试。当通过Ctrl-C
停止命令时,所有容器将会停止。如果想要在后台启动所有容器,可以使用docker-compose up -d
,推荐生产环境使用该选项 - 默认情况下,如果服务容器已经存在,
docker-compose up
将会尝试停止容器,然后重新创建(保持使用volumes
挂载的数据卷),以保证新启动的服务匹配docker-compose.yml
文件的最新内容
我们编写如下模板文件来测试,模板文件放在mytomcatapp
目录下
version: "3.2" # 指定compose的版本
services:
tomcat1: # 代表一个容器的服务名称,在文件中必须唯一
image: tomcat:8.0-jre8 # 指定用哪个镜像来创建这个容器
ports:
- "8080:8080" # 指定容器与宿主机的端口映射
volumes:
- webapp1:/usr/local/tomcat/webapps
tomcat2:
image: tomcat:8.0-jre8
ports:
- "8081:8080"
volumes:
- webapp2:/usr/local/tomcat/webapps
volumes:
webapp1:
webapp2:
启动时指定后台运行与项目名称
docker-compose up -d
运行后可以发现,compose帮我们自动创建了项目的网络、数据卷、容器
此时我们尝试修改模板文件中容器的端口映射
然后再次运行compose up指令,会发现docker-compose能判断出tomcat1没有被修改,无需重新构建启动。tomcat2重新映射新的端口启动。并且原来的网络、数据卷都还在
如果不修改任何模板文件内容,在服务容器已经启动的情况下再次运行docker-compose up -d
,将不会有任何效果
3.2 down
停止并删除up
命令所启动的容器,并移除网络
我们在up命令执行后执行down命令,会发现up启动的容器将被停止并删除,同时容器网络也会被删除,但是数据卷会被保留
3.3 ps
列出项目中目前的所有容器,格式为docker-compose ps [options] [SERVICE...]
选项:
-q
:只打印容器的id信息
3.4 restart
重启项目中的服务,格式为docker-compose restart [options] [SERVICE...]
选项:
-t,--timeout TIMEOUT
:指定重启前停止容器的超时,默认为10秒
3.5 rm
删除所有停止状态的服务容器,格式为docker-compose rm [options] [SERVICE...]
在执行该命令前推荐先执行docker-compose stop
命令来停止容器
选项:
-f,--force
:强制直接删除,包括非停止状态的容器。尽量不要用该选项-v
:删除容器所挂载的数据卷
3.6 start
启动已经存在的服务容器。格式为docker-compose start [SERVICE...]
3.7 stop
停止已经处于运行状态的容器,但不删除它。通过docker-compose start
可以再次启动这些容器
选项:
-t,--timeout TIMEOUT
:停止容器时候的超时,默认为10秒
3.8 top
查看各个服务容器内运行的进程
3.9 pause/unpause
暂停/恢复服务容器,格式为docker-compose pause/unpause [SERVICE...]