Docker-Compose 项目是 Docker 官方的开源项目,是用于定义和运行多容器 Docker 应用程序的工具。负责实现对 Docker 容器集群的快速编排。 通过 Compose,可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。
Docker-Compose 将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker-Compose 运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。
一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例,Docker-Compose 并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡。
Docker-Compose 的工程配置文件默认为 docker-compose.yml,可通过环境变量 COMPOSE_FILE 或 -f 参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。
使用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。在工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
Compose 允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。 Docker-Compose 项目由 Python 编写,调用 Docker 服务提供的 API 来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用 Compose 来进行编排管理。
Docker-compose 安装
# 要安装其他版本的 Compose,请替换 v2.2.2。
sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose -v
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
Docker-compose卸载
apt-get remove docker-compose
docker-compose ps
docker-compose logs [options] [SERVICE...]
# 选项包括
–no-color 关闭颜色。默认情况下,docker-compose将对不同的服务输出使用不同的颜色来区分
-f 跟踪日志输出
。
# 示例
docker-compose logs
up:使用当前目录下的docker-compose.yaml文件构建、启动、更新容器
当服务的配置发生更改时,可使用 docker-compose up 命令更新配置
此时,Compose 会删除旧容器并创建新容器,新容器会以不同的 IP 地址加入网络,名称保持不变,任何指向旧容起的连接都会被关闭,重新找到新容器并连接上去
docker-compose up [options] [--scale SERVICE=NUM...] [SERVICE...]
# 选项包括:
-f # 指定yml部署模板文件
-d # 在后台运行服务容器
--force-recreate # 强制重新创建容器,不能与-no-recreate同时使用
-no-recreate # 如果容器已经存在,则不重新创建,不能与–force-recreate同时使用
-no-color # 不用颜色来区分不同的服务的控制输出
-no-deps # 不启动服务所链接的容器
-no-build # 不自动构建缺失的服务镜像
-build # 在启动容器前构建服务镜像
-V, --renew-anon-volumes # 重新创建匿名卷,而不是从以前的容器中检索数据
-abort-on-container-exit # 如果任何一个容器被停止,则停止所有容器。不能与-d同时使用
-t, -timeout TIMEOUT # 停止容器时候的超时(默认为10秒)
-remove-orphans # 删除服务中没有在compose.yaml文件中定义的容器
--scale SERVICE=NUM # 将Compose.yaml中的SERVICE服务扩展到NUM个实例,快速实现一个负载均衡(单节点)
# 该参数会覆盖Compose.yaml文件中的“scale”设置(如果存在)。
# 注意:如果Compose.yaml中设置了ports配置(端口绑定)
# ,当使用scale参数拓展到多个实例时,会端口冲突,需删除Compose.yaml中的ports配置
# 示例
docker-compose up --force-recreate -d
docker-compose port [options] SERVICE PRIVATE_PORT
# 选项包括:
–protocol=proto 指定端口协议,TCP(默认值)或者UDP
–index=index 如果同意服务存在多个容器,指定命令对象容器的序号(默认为1)
# 示例:下面命令可以输出 eureka 服务 8761 端口所绑定的公共端口
docker-compose port eureka 8761
build:构建或者重新构建服务容器。
服务容器一旦构建后,将会带上一个标记名。可以随时在项目目录下运行docker-compose build来重新构建服务
docker-compose build [options] [--build-arg key=val...] [SERVICE...]
# 选项包括:
–compress 通过gzip压缩构建上下环境
–force-rm 删除构建过程中的临时容器
–no-cache 构建镜像过程中不使用缓存
–pull 始终尝试通过拉取操作来获取更新版本的镜像
-m, –memory MEM 为构建的容器设置内存大小
–build-arg key=val 为服务设置build-time变量
# 示例:
docker-compose build
docker-compose stop [options] [SERVICE...]
# 选项包括
-t, –timeout TIMEOUT 停止容器时候的超时(默认为10秒)
# 示例
docker-compose stop eureka
docker-compose start [SERVICE...]
# 示例
docker-compose start eureka
docker-compose restart [options] [SERVICE...]
# 选项包括:
-t, –timeout TIMEOUT 指定重启前停止容器的超时(默认为10秒)
# 示例:
docker-compose restart
docker-compose rm [options] [SERVICE...]
# 选项包括:
–f, –force 强制直接删除,包括非停止状态的容器
-v 删除容器所挂载的数据卷
# 示例
docker-compose rm eureka
docker-compose kill [options] [SERVICE...]
# 选项包括:
-s 来指定发送的信号
# 示例
docker-compose kill eureka
docker-compose kill -s SIGINT
docker-compose push [options] [SERVICE...]
# 选项包括:
–ignore-push-failures 忽略推送镜像过程中的错误
docker-compose pull [options] [SERVICE...]
# 选项包括:
–ignore-pull-failures 忽略拉取镜像过程中的错误
–parallel 多个镜像同时拉取
–quiet 拉取镜像过程中不打印进度信息
# 示例
docker-compose pull
docker-compose scale user=3 movie=3
docker-compose run web bash
docker-compose down [options]
# 选项包括:
–rmi type 删除镜像,类型必须是:all,删除compose文件中定义的所有镜像;local,删除镜像名为空的镜像
-v, –volumes 删除已经在compose文件中定义的和匿名的附在容器上的数据卷
–remove-orphans 删除服务中没有在compose中定义的容器
# 示例
docker-compose down
docker-compose pause [SERVICE...]
docker-compose unpause [SERVICE...]
docker-compose config [options]
# 选项包括:
–resolve-image-digests 将镜像标签标记为摘要
-q, –quiet 只验证配置,不输出。 当配置正确时,不输出任何内容,当文件配置错误,输出错误信息
–services 打印服务名,一行一个
–volumes 打印数据卷名,一行一个
docker-compose create [options] [SERVICE...]
# 选项包括:
–force-recreate 重新创建容器,即使配置和镜像没有改变,不兼容–no-recreate参数
–no-recreate 如果容器已经存在,不需要重新创建,不兼容–force-recreate参数
–no-build 不创建镜像,即使缺失
–build 创建容器前,生成镜像
Compose允许用户通过一个docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。 Compose模板文件是一个定义服务、网络和卷的YAML文件。Compose模板文件默认路径是当前目录下的docker-compose.yml,可以使用.yml或.yaml作为文件扩展名。
Docker-Compose标准模板文件应该包含version、services、networks 三大部分,最关键的是services和networks两个部分。
示例模板
version: '3'
networks:
front-tier:
driver: bridge
back-tier:
driver: bridge
services:
web:
image: dockercloud/hello-world
ports:
- 8080
networks:
- front-tier
- back-tier
redis:
image: redis
links:
- web
networks:
- back-tier
lb:
image: dockercloud/haproxy
ports:
- 80:80
links:
- web
networks:
- front-tier
- back-tier
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Compose目前有三个版本分别为Version 1,Version 2,Version 3,Compose区分Version 1和Version 2(Compose 1.6.0+,Docker Engine 1.10.0+)。Version 2支持更多的指令。Version 1将来会被弃用。
启动应用
创建一个webapp目录,将docker-compose.yaml文件拷贝到webapp目录下,使用docker-compose启动应用。
docker-compose up -d
version:指定 docker-compose.yml 文件的写法格式
services:多个容器集合
build:指定为构建镜像上下文路径。相对路径、绝对路径均可
服务除了可以基于指定的镜像,还可以基于一份Dockerfile,在使用up启动时执行构建任务,构建标签是build,可以指定Dockerfile所在文件夹的路径。Compose将会利用Dockerfile自动构建镜像,然后使用镜像启动服务容器。
build: ./dir
---------------
build:
context: /path/to/build/dir
dockerfile: Dockerfile
args:
buildno: 1
labels:
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
target: prod
# build都是一个目录,如果要指定Dockerfile文件需要在build标签的子级标签中使用dockerfile标签指定。
# 如果同时指定image和build两个标签,那么Compose会构建镜像并且把镜像命名为image值指定的名字。
container_name: my-web-container
command:覆盖容器启动后默认执行的命令
在用命令行运行容器时,有的容器需要在命令中加入附加的命令行参数,这就需要加在compose文件的服务中的command中。这一个参数没有什么固定的模式,建议按照对应容器的镜像的使用说明来决定是否需要加,加什么。
command: bundle exec thin -p 3000
----------------------------------
command: ["bundle","exec","thin","-p","3000"]
cap_add:
- ALL # 开启全部权限
cap_drop:
- SYS_PTRACE # 关闭 ptrace权限
version: "3.7"
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
dns: 8.8.8.8
------------
dns:
- 8.8.8.8
- 9.9.9.9
dns_search: example.com
------------------------
dns_search:
- dc1.example.com
- dc2.example.com
env_file: .env
---------------
env_file:
- ./common.env
environment:
RACK_ENV: development
SHOW: 'ture'
-------------------------
environment:
- RACK_ENV=development
- SHOW=ture
expose:
- "3000"
- "8000"
ports:对外暴露的端口定义,和 expose 对应
注意:ports属性是物理机和集群网络中服务(而不是ingress)之间的映射,容器访问ingress网络中的某个地址时,是无法根据端口做转发的。
若使用了ports,则该服务会生成两个虚拟ip,一个是服务间通信的overlay网络虚拟ip,一个是用于映射服务端口到物理机端口的ingress网络虚拟ip,这时服务注册到注册中心(比如nacos)的ip很可能会是ingress网络虚拟ip,最终会导致基于注册中心服务发现的gateway路由和feign调用不通(超时)。
解决方案为:
若不用暴露端口给物理机,则只使用expose暴露端口到集群网络,这种可以注册正确的虚拟ip到注册中心
若必须暴露端口给物理机,则配置文件中设定容器虚拟网段
spring:
application:
name: @artifactId@
cloud:
inetutils:
ignored-interfaces: eth.*
preferred-networks: 192.168.0
详见:https://my.oschina.net/woniuyi/blog/4984748
# 暴露端口信息。格式:- "宿主机端口:容器暴露端口",或者只是指定容器的端口,宿主机会随机映射端口。
ports:
- "8763:8763"
- "8763:8763"
# 当使用HOST:CONTAINER格式来映射端口时,如果使用的容器端口小于60可能会得到错误得结果,因为YAML将会解析xx:yy这种数字格式为60进制。所以建议采用字符串格式。
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
# 以上会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:
162.242.195.82 somehost
50.31.209.229 otherhost
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
interval: 1m30s # 设置检测间隔
timeout: 10s # 设置检测超时时间
retries: 3 # 设置重试次数
start_period: 40s # 启动后,多少秒开始启动检测程序
# 以下格式都可以:
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id
links:将指定容器连接到当前连接,可以设置别名,避免ip方式导致的容器重启动态改变的无法连接情况。
在用命令行部署容器的时候,经常会需要在一个容器里面访问另外一个容器,这个时候就需要用到 --link参数,一般的使用形式为 --link [引用的其他容器名]:[容器内代表引用容器的字段]
。被 --link A:B形式引用的A容器会以[A 的 ip:port] : 'B’的形式出现在容器内的/etc/hosts文件里。也就是说,经过 --link 引入的其他容器A将自己的地址和端口赋给了字段B。在容器内需要获得A的时候,可以直接使用字段B。
注意:在v3版本的compose file中,links属性是会自动被 docker stack deploy命令忽略的,因为在v3中,links的功能已经移除。作为替代的是networks属性。
links:
# 指定服务名称:别名
- docker-compose-eureka-server:compose-eureka
# 仅指定服务名称(同时作为别名)
- db
--no-color 单色输出,不显示其他颜.
-f, --follow 跟踪日志输出,就是可以实时查看日志
-t, --timestamps 显示时间戳
--tail 从日志的结尾显示,--tail=200
logging:日志输出控制
linux上,容器日志一般存放在 /var/lib/docker/containers/CONTAINER_ID/ 下面,以 json.log 结尾的文件
logging:
driver: "json-file"
options:
max-size: "5g" # 日志文件的大小限制在5GB
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
networks:
some-network:
# 使用自定义驱动程序
driver: custom-driver-1
other-network:
# 引用外部网络
external: true
services:
some-service:
networks:
some-network:
aliases:
- alias1
other-network:
aliases:
- alias2
restart
注:swarm 集群模式,请改用 restart_policy。
restart: "no"
------------------------------
restart: always
------------------------------
restart: on-failure
------------------------------
restart: unless-stopped
security-opt:
- label:user:USER # 设置容器的用户标签
- label:role:ROLE # 设置容器的角色标签
- label:type:TYPE # 设置容器的安全策略标签
- label:level:LEVEL # 设置容器的安全等级标签
tmpfs: /run
------------------------------
tmpfs:
- /run
- /tmp
volumes:将主机的数据卷或着文件挂载到容器里
可以直接使用 [HOST:CONTAINER]格式,或者使用[HOST:CONTAINER:ro]格式,后者对于容器来说,数据卷是只读的,可以有效保护宿主机的文件系统。 Compose的数据卷指定路径可以是相对路径,使用 . 或者 … 来指定相对目录。
volumes对应命令行中的 -v 选项,其本身的意义并没有发生什么变化。但是,由于volume在yml文件中是以字符串的形式存在的,所以像 $PWD 这样的写法是不能被接受的,要改成相对路径或绝对路径。
# 数据卷的格式可以是下面多种形式
volumes:
# 只是指定一个路径,Docker 会自动在创建一个数据卷(这个路径是容器内部的)。
- /var/lib/mysql
# 使用绝对路径挂载数据卷
- /opt/data:/var/lib/mysql
# 以 Compose 配置文件为中心的相对路径作为数据卷挂载到容器。
- ./cache:/tmp/cache
# 使用用户的相对路径(~/ 表示的目录是 /home/<用户目录>/ 或者 /root/)。
- ~/configs:/etc/configs/:ro
# 已经存在的命名的数据卷。
- datavolume:/var/lib/mysql
# 如果不使用宿主机的路径,可以指定一个volume_driver。
volumes_from:
- service_name
- container_name
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000