#|docker-compose容器编排

本文从本人博客搬运,原文格式更加美观,可以移步原文阅读: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来统一编排管理这一组容器
#|docker-compose容器编排
文章图片

安装 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检查安装是否成功
#|docker-compose容器编排
文章图片

2.win/mac win/mac平台安装docker后就自带docker-compose,可以直接使用
具体使用 1.入门 使用docker-compose的基本步骤如下:
  1. 编写docker-compose.yml模板文件,指定要编排运行的一组容器
  2. 利用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

#|docker-compose容器编排
文章图片

可以发现启动时,由于镜像不存在,compose先帮我们自动下载了镜像,然后启动2个tomcat容器,并且2个容器的日志颜色会进行区分
#|docker-compose容器编排
文章图片

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模板文件所在的目录名
#|docker-compose容器编排
文章图片

如果不想使用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
【#|docker-compose容器编排】配置容器使用哪个网络(桥)
version: "3.2"services: mytomcat: image: tomcat:8.0-jre8 ports: - "8080:8080" networks: - mynetwork# 指定容器连接哪个网络。指定的自定义网络名称必须在下面定义networks: mynetwork:# 定义网络。定义后才能在上面使用,否则报错

启动容器后,compose会自动帮我们创建mynetwork网络
#|docker-compose容器编排
文章图片

可以看出:
  • 如果我们在模板文件中没有指定容器用的网络,那么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"

#|docker-compose容器编排
文章图片

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.7redis5: 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.7redis5: 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=...] [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/webappsvolumes: webapp1: webapp2:

启动时指定后台运行与项目名称
docker-compose up -d

运行后可以发现,compose帮我们自动创建了项目的网络、数据卷、容器
#|docker-compose容器编排
文章图片

此时我们尝试修改模板文件中容器的端口映射
#|docker-compose容器编排
文章图片

然后再次运行compose up指令,会发现docker-compose能判断出tomcat1没有被修改,无需重新构建启动。tomcat2重新映射新的端口启动。并且原来的网络、数据卷都还在
#|docker-compose容器编排
文章图片

如果不修改任何模板文件内容,在服务容器已经启动的情况下再次运行docker-compose up -d,将不会有任何效果
#|docker-compose容器编排
文章图片

3.2 down
停止并删除up命令所启动的容器,并移除网络
我们在up命令执行后执行down命令,会发现up启动的容器将被停止并删除,同时容器网络也会被删除,但是数据卷会被保留
#|docker-compose容器编排
文章图片

3.3 ps
列出项目中目前的所有容器,格式为docker-compose ps [options] [SERVICE...]
选项:
  • -q:只打印容器的id信息
#|docker-compose容器编排
文章图片

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
查看各个服务容器内运行的进程
#|docker-compose容器编排
文章图片

3.9 pause/unpause
暂停/恢复服务容器,格式为docker-compose pause/unpause [SERVICE...]
#|docker-compose容器编排
文章图片

    推荐阅读