Docker三剑客之Compose
一、 概述
compose 是用来定义和运行一个或多个容器(通常都是多个)运行和应用的工具。使用 compose 可以简化容器镜像的构建以及容器的运行。
compose 使用 YAML 文件来定义多容器之间的关系。一个 docker-compose up 就可以把完整的应用跑起来。 本质上,compose 把 YAML 文件解析成 docker 命令的参数,然后调用相应的 docker命令行接口,从而将应用以容器化的方式管理起来。它通过解析容器间的依赖关系顺序地启动容器。而容器间的依赖关系由 YAML 文件中的 links标记指定。
二、安装
1)二进制包安装(推荐)
$ curl -L https://github.com/docker/compose/releases/download/1.23.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
$ docker-compose version
2)pip 安装(安装的是最新稳定版本)
# 环境centos8,先安装python3
$ yum -y install python38
$ pip3 install docker-compose
# 做软链接
$ ln -s /usr/bin/docker-compose /usr/local/bin/
三、Compose命令简介
1)常看帮助
docker-compose [COMMAND] --help 或者docker-compose help [COMMAND]
$ docker-compose --help
$ docker-compose -h
使用格式
docker-compose [-f
...] [--profile ...] [options] [--] [COMMAND] [ARGS...]
Options参数选项
-f,--file file指定模板文件,默认是docker-compose.yml模板文件,可以多次指定
--profile 启动具有配置文件的服务
-p,--project-name name指定项目名称,默认使用所在目录名称作为项目名称
--x-networking 使用Docker的后端可插拔网络特性
--x-networking-driver driver指定网络的后端驱动,默认使用bridge
--verbose 输入更多的调试信息
-v,--version 输出版本信息
COMMAND参数详解
build Build or rebuild services (构建项目中的服务容器)
bundle Generate a Docker bundle from the Compose file (从Compose文件生成分布式应用程序包)
config Validate and view the Compose file (验证并查看Compose文件)
create Create services (为服务创建容器)
down Stop and remove containers, networks, images, and volumes (停止容器并删除由其创建的容器,网络,卷和图像up)
events Receive real time events from containers (为项目中的每个容器流式传输容器事件)
exec Execute a command in a running container (这相当于docker exec。使用此子命令,您可以在服务中运行任意命令。默认情况下,命令分配TTY,因此您可以使用命令docker-compose exec web sh来获取交互式提示。)
help Get help on a command (获得一个命令的帮助)
images List images ()
kill Kill containers (通过发送SIGKILL信号来强制停止服务容器)
logs View output from containers (查看服务容器的输出)
pause Pause services (暂停一个容器)
port Print the public port for a port binding (打印某个容器端口所映射的公共端口)
ps List containers (列出项目中目前所有的容器)
pull Pull service images (拉取服务依赖镜像)
push Push service images (推送服务镜像)
restart Restart services (重启项目中的服务)
rm Remove stopped containers (删除所有停止状态的服务容器)
run Run a one-off command (在指定服务上执行一个命令)
scale Set number of containers for a service (设置指定服务执行的容器个数)
start Start services (启动已存在的服务容器)
stop Stop services (停止已存在的服务容器)
top Display the running processes (显示容器正在运行的进程)
unpause Unpause services (恢复处于暂停状态的容器)
up Create and start containers (自动完成包括构建镜像、创建服务、启动服务并关联服务相关容器的一系列操作)
version Show the Docker-Compose version information (输出版本)
2)环境变量
COMPOSE_PROJECT_NAME 设置通过 Compose 启动的每一个容器前添加的项目名称,默认是当前工作目录的名字。
COMPOSE_FILE 设置要使用的 docker-compose.yml 的路径。默认路径是当前工作目录。
DOCKER_HOST 设置 Docker daemon 的地址。默认使用 unix:///var/run/docker.sock,与 Docker 客户端采用的默认值一致。
DOCKER_TLS_VERIFY 如果设置不为空,则与 Docker daemon 交互通过 TLS 进行。
DOCKER_CERT_PATH 配置 TLS 通信所需要的验证(ca.pem、cert.pem 和 key.pem)文件的路径,默认是 ~/.docker
四、Docker-Compose YAML语法使用说明
- version
docker-compose文件使用哪个version的file格式
目前有三个版本的 Compose 文件格式1,2.x,3.x。version版本统一用3,其实3是兼容2的,version版本1 就不要考虑了已经废弃了,一定要往前看。
version: '3'
- build
这个是创建docker镜像时的选项,通过本地的dockerfile来创建,而不是通过image id来pull。
build:
context: ./nginx # 指定构建镜像的路径
dockerfile: Dockerfile # 选项是备选的dockerfile
args: # 参数设置
- buildno=1
- user=someuser
- image
生成镜像的ID,指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉去这个镜像。
image: ubuntu
image: orchardup/postgresql
- links
链接到其它服务中的容器,使一个容器可以主动的去和另外一个容器通讯。使用服务名称(同时作为别名)或服务名称:服务别名 (SERVICE:ALIAS) 格式都可以。
links:
- db
- db:database
- redis
使用的别名将会自动在服务容器中的 /etc/hosts 里创建,相应的环境变量也将被创建。例如
172.17.2.186 db
172.17.2.186 database
172.17.2.187 redis
- external_links
链接到 docker-compose.yml 外部的容器,甚至 并非 Compose 管理的容器。参数格式跟 links 类似。
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql
- expose
这个是给link用的,将一些端口暴露给link到这个container上的containers。暴露端口,但不映射到宿主机,只被连接的服务访问
expose:
- "3000"
- "8000"
- ports
暴露端口信息,这个是将端口和本机端口映射的选项,写法如下,其实跟docker -p一样。使用宿主:容器 (HOST:CONTAINER)格式或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。
ports:
- "3000"
- "3000-3005"
- "80:80"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
注:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 你可能会得到错误得结果,因为 YAML 将会解析 xx:yy 这种数字格式为 60 进制。所以建议采用字符串格式。
- environment
设置环境变量。你可以使用数组或字典两种格式。
只给定名称的变量会自动获取它在 Compose 主机上的值,可以用来防止泄露不必要的数据。
environment:
RACK_ENV: development
SESSION_SECRET:
environment:
- RACK_ENV=development
- SESSION_SECRET
- env_file
从文件中获取环境变量,可以为单独的文件路径或列表。
如果通过 docker-compose -f FILE 指定了模板文件,则 env_file 中路径会基于模板文件路径。
如果有变量名称与 environment 指令冲突,则以后者为准。
env_file: .env
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
- volumes
将本机的文件夹挂载到container中。
volumes:
# Just specify a path and let the Engine create a volume
- /var/lib/mysql
# Specify an absolute path mapping
- /opt/data:/var/lib/mysql
# User-relative path
- ~/configs:/etc/configs/:ro
# Named volume
- datavolume:/var/lib/mysql
卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro)
volumes:
- /var/lib/mysql
- cache/:/tmp/cache
- ~/configs:/etc/configs/:ro
- volumes_from
从另一个服务或容器挂载它的所有卷。
volumes_from:
- service_name
- container_name
- extends
基于已有的服务进行扩展。例如我们已经有了一个webapp服务,模板文件为 common.yml。
# common.yml
webapp:
build: ./webapp
environment:
- DEBUG=false
- SEND_EMAILS=false
编写一个新的 development.yml 文件,使用 common.yml 中的 webapp 服务进行扩展。
# development.yml
web:
extends:
file: common.yml
service: webapp
ports:
- "8000:8000"
links:
- db
environment:
- DEBUG=true
db:
image: postgres
后者会自动继承 common.yml 中的 webapp 服务及相关环节变量。
- net
设置网络模式。使用和 docker client 的 –net 参数一样的值。
net: "bridge"
net: "none"
net: "container:[name or id]"
- pid
跟主机系统共享进程命名空间。打开该选项的容器可以相互通过进程 ID 来访问和操作。
pid: "host"
- dns
配置 DNS 服务器。可以是一个值,也可以是一个列表。
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
- cap_add, cap_drop
添加或放弃容器的 Linux 能力(Capabiliity)。
cap_add:
- ALL
cap_drop:
- NET_ADMIN
- SYS_ADMIN
- dns_search
配置 DNS 搜索域。可以是一个值,也可以是一个列表。
dns_search: example.com
dns_search:
- domain1.example.com
- domain2.example.com
- command
覆盖容器启动后默认执行的命令。
command: bundle exec thin -p 3000
- restart
定义容器重启策略(在使用 swarm 部署时将忽略该选项, 在 swarm 使用 restart_policy 代替 restart)。重启策略如下:
- no,默认策略,在容器退出时不重启容器
- on-failure,在容器非正常退出时(退出状态非0),才会重启容器
- on-failure:3,在容器非正常退出时重启容器,最多重启3次
- always,在容器退出时总是重启容器
- unless-stopped,在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
tomcat:
restart: always
- 其它选项
working_dir, entrypoint, user, hostname, domainname, mem_limit, privileged, restart, stdin_open, tty, cpu_sharesv 这些都是和 docker run 支持的选项类似。
cpu_shares: 73
working_dir: /code
entrypoint: /code/entrypoint.sh
user: postgresql
hostname: foo
domainname: foo.com
mem_limit: 1000000000
privileged: true
restart: always
stdin_open: true
tty: true
五、实战讲解
1)Docker-compose搭建Redis-jenkins
$ mkdir -p /opt/docker-composer-test/jenkins_home
$ cd /opt/docker-composer-test/jenkins_home
用docker-compose安装,当然你也可以用docker run的方式,创建一个docker-jenkins-compose.yml文件。
version: "3"
services:
jenkins:
image: jenkins/jenkins:lts
ports:
- 8080:8080
- 50000:50000
restart: "always"
container_name: jenkins
environment:
JAVA_OPTS: -Duser.timezone=Asia/Shanghai
volumes:
- /opt/docker-composer-test/jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker
privileged: true
user: root
启动Jenkins容器
$ docker-compose -f docker-jenkins-compose.yml up -d
2)Docker-compose搭建Redis Sentinel(哨兵模式)
Redis Sentinel是针对原始Master/Slave模型而衍生的高可用模型。我们为便于灵活部署,先易后难,先搭建Redis Master/Slave模型,再搭建Redis Sentinel模型。
目录结构如下,先创建如下目录文件。
[root@Centos8-nat-bridge-168-182-153 redis_sentinel]# tree .
.
├── redis
│?? └── docker-compose.yml
└── sentinel
├── docker-compose.yml
├── sentinel1.conf
├── sentinel2.conf
├── sentinel3.conf
└── sentinel.conf
第一步:搭建Redis Master/Slave模型
下面的Compose文件设置了redis的 一主两从(Master-Slave)
1、创建redis/docker-compose.yml文件。
version: '3'
services:
master:
image: redis
container_name: redis-master
command: redis-server --requirepass redis_pwd --masterauth redis_pwd
ports:
- 6379:6379
slave1:
image: redis
container_name: redis-slave-1
ports:
- 6380:6379
command: redis-server --slaveof redis-master 6379 --requirepass redis_pwd --masterauth redis_pwd
slave2:
image: redis
container_name: redis-slave-2
ports:
- 6381:6379
command: redis-server --slaveof redis-master 6379 --requirepass redis_pwd --masterauth redis_pwd
注意,如果设置了Redis客户端访问密码requirepass, 那么也要设置相同的副本集同步密码masterauth。
另外我们后面使用哨兵模式能够完成故障转移,现有的Master可能会变成Slave,故在当前Master容器中也要携带masterauth参数。
2、执行 以下命令 产生3个Redis容器,分别映射到宿主机6379、6380、6381端口, 默认连接在redis-default网桥。
$ docker-compose -f redis/docker-compose.yml up -d
3、使用docker ps查看redis三个容器
$ docker ps -a
4、查看redis容器使用的网桥信息
$ docker inspect -f {{.HostConfig.NetworkMode}} 262b42fb0c9f
5、验证
Master/Slave副本集,进入Master容器,确认两个Slave容器已经连接。
redis/docker-compose.yml里面的redis密码我改成了:123456
第二步:docker-compose 部署Redis Sentinel
我们即将搭建的Sentinel容器需要能访问到以上3个容器,故需要在形成Sentinel容器时使用外置的redis-default网桥(Redis Master/Slave docker-compose 已经创建).
1、创建sentinel/docker-compose.yml,内容如下:
version: '3'
services:
sentinel1:
image: redis
container_name: redis-sentinel-1
ports:
- 26379:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel1.conf:/usr/local/etc/redis/sentinel.conf
sentinel2:
image: redis
container_name: redis-sentinel-2
ports:
- 26380:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel2.conf:/usr/local/etc/redis/sentinel.conf
sentinel3:
image: redis
container_name: redis-sentinel-3
ports:
- 26381:26379
command: redis-sentinel /usr/local/etc/redis/sentinel.conf
volumes:
- ./sentinel3.conf:/usr/local/etc/redis/sentinel.conf
networks:
default:
external:
name: redis_default
2、创建哨兵文件sentinel/sentinel.conf,内容如下:
port 26379
dir /tmp
sentinel monitor mymaster 172.19.0.3 6379 2
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
注意,以上 172.19.0.3是之前Redis Master/slave启动之后Master节点的IP,通过docker inspect [container]获取, 这里我们要配合设置Master/Slave访问密码:123456。
查看redis-master IP地址
$ docker inspect --format='{{.NetworkSettings.Networks.redis_default.IPAddress}}' redis-master
#或者
$ docker inspect redis-master
3、将哨兵文件复制三份
$ cp sentinel/sentinel.conf sentinel/sentinel1.conf
$ cp sentinel/sentinel.conf sentinel/sentinel2.conf
$ cp sentinel/sentinel.conf sentinel/sentinel3.conf
4、执行以下命令生成3个Sentinel容器。
$ docker-compose -f sentinel/docker-compose.yml up -d
5、此时docker ps显示如下:
$ docker ps
6、验证
进入其中一个redis-sentinel容器,确认Master、2个Slave、另外2个Sentinel.
$ docker exec -it redis-sentinel-1 /bin/bash
$ redis-cli -p 26379
$ sentinel master mymaster
- flags: master表明master正常运作,异常情况会显示s-down,o-down
- num-slaves:侦测到2个Slave副本集
- num-other-sentinels:除此之外,还有2个哨兵
7、Redis Sentinel高可用验证
停止 redis-master容器,等待10s,进入任意sentinel容器,使用sentinel master mymaster命令观察主节点发生变化,观察外挂的Sentinel*.conf主节点IP发生变化,然后重新启动master节点,检查集群状态.
$ docker stop redis-master
$ docker exec -it redis-sentinel-1 /bin/bash
$ redis-cli -p 26379
$ sentinel master mymaster
发现master节点以及s_down状态了。
六、Docker Compose 常用命令
命令 | 说明 |
---|---|
docker-compose build | 构建项目中的镜像,--force-rm:删除构建过程中的临时容器;--no-cache:不使用缓存构建;--pull:获取最新版本的镜像 |
docker-compose up -d | 构建镜像、创建服务和启动项目,-d表示后台运行 |
docker-compose run ubuntu ls -d | 指定服务上运行一个命令,-d表示后台运行 |
docker-compose logs | 查看服务容器输出日志 |
docker-compose ps | 列出项目中所有的容器 |
docker-compose pause [service_name] | 暂停一个服务容器 |
docker-compose unpause [service_name] | 恢复已暂停的一个服务容器 |
docker-compose restart | 重启项目中的所有服务容器(也可以指定具体的服务) |
docker-compose stop | 停止运行项目中的所有服务容器(也可以指定具体的服务) |
docker-compose start | 启动已经停止项目中的所有服务容器(也可以指定具体的服务) |
docker-compose rm | 删除项目中的所有服务容器(也可以指定具体的服务),-f:强制删除(包含运行的) |
docker-compose kill | 强制停止项目中的所有服务容器(也可以指定具体的服务) |