1. 什么是docker-compose
Docker Compose是一个用来定义和运行复杂应用的Docker工具。一个使用Docker容器的应用,通常由多个容器组成。使用Docker Compose不再需要使用shell脚本来启动容器。
Compose 通过一个配置文件来管理多个Docker容器,在配置文件中,所有的容器通过services来定义,然后使用docker-compose脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器,非常适合组合使用多个容器进行开发的场景。
2. 安装
docker-compose安装可以参考官方文档:Install Docker Compose
2.1. macOs
Docker Desktop for Mac
和 Docker Toolbox
已集成了docker-compose, 所以只要安装了docker是不需要安装的,直接就可以用。
2.2. Linux
在Linux系统中,可以通过源码来安装docker-compose
-
从github下载最新版docker-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
-
给docker-compose赋予可执行权限
sudo chmod +x /usr/local/bin/docker-compose
最后可以通过以下命令来验证是否安装成功:
docker-compose --version
3. 语法
docker-compose 文件命名以.yml
或.yaml
为后缀。
下面先欣赏一下官方文档中的一个示例:
version: "3"services: redis: image: redis:alpine ports: - "6379" networks: - frontend deploy: replicas: 2 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure db: image: postgres:9.4 volumes: - db-data:/var/lib/postgresql/data networks: - backend deploy: placement: constraints: [node.role == manager] vote: image: dockersamples/examplevotingapp_vote:before ports: - "5000:80" networks: - frontend depends_on: - redis deploy: replicas: 2 update_config: parallelism: 2 restart_policy: condition: on-failure result: image: dockersamples/examplevotingapp_result:before ports: - "5001:80" networks: - backend depends_on: - db deploy: replicas: 1 update_config: parallelism: 2 delay: 10s restart_policy: condition: on-failure worker: image: dockersamples/examplevotingapp_worker networks: - frontend - backend deploy: mode: replicated replicas: 1 labels: [APP=VOTING] restart_policy: condition: on-failure delay: 10s max_attempts: 3 window: 120s placement: constraints: [node.role == manager] visualizer: image: dockersamples/visualizer:stable ports: - "8080:8080" stop_grace_period: 1m30s volumes: - "/var/run/docker.sock:/var/run/docker.sock" deploy: placement: constraints: [node.role == manager] networks: frontend: backend: volumes: db-data:
从上述示例看,整个文档分为4部分,version
, services
, networks
, volumes
, 其中services
中内容最长,下面将一一做个简单介绍
3.1. version
version是compose的版本,下表是compose版本与docker版本对照表:
Compose file format | Docker Engine release |
---|---|
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.+ |
3.2. services
services是用来配置定义每个容器启动参数,每个service就是一个容器,services下一级配置即是服务名称,例如上面示例中的redis, db等。
3.2.1. image
image是指定服务的镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。
例如下面这些格式都是可以的:
image: redisimage: ubuntu:14.04image: tutum/influxdbimage: example-registry.com:4000/postgresqlimage: a4bc65fd
3.2.2. build
服务除了可以基于指定的镜像,还可以基于一份 Dockerfile,在使用 up 启动之时执行构建任务,这个构建标签就是 build,它可以指定 Dockerfile 所在文件夹的路径。Compose 将会利用它自动构建这个镜像,然后使用这个镜像启动服务容器。
build: /path/to/build/dir
也可以是相对路径,只要上下文确定就可以读取到 Dockerfile。
build: ./dir
设定上下文根目录,然后以该目录为准指定 Dockerfile。
build: context: ../ dockerfile: path/of/Dockerfile
注意 build 都是一个目录,如果你要指定 Dockerfile 文件需要在 build 标签的子级标签中使用 dockerfile 标签指定,如上面的例子。
如果你同时指定了 image 和 build 两个标签,那么 Compose 会构建镜像并且把镜像命名为 image 后面的那个名字。
既然可以在 docker-compose.yml 中定义构建任务,那么一定少不了 arg 这个标签,就像 Dockerfile 中的 ARG 指令,它可以在构建过程中指定环境变量,但是在构建成功后取消,在 docker-compose.yml 文件中也支持这样的写法:
build: context: . args: buildno: 1 password: secret
下面这种写法也是支持的,一般来说下面的写法更适合阅读。
build: context: . args: - buildno=1 - password=secret
与 ENV 不同的是,ARG 是允许空值的。例如:
args: - buildno - password
这样构建过程可以向它们赋值。
注意:YAML 的布尔值(true, false, yes, no, on, off)必须要使用引号引起来(单引号、双引号均可),否则会当成字符串解析。
3.2.3. command
使用 command 可以覆盖容器启动后默认执行的命令。
command: bundle exec thin -p 3000
也可以写成类似 Dockerfile 中的格式:
command: [bundle, exec, thin, -p, 3000]
3.2.4. container_name
Compose 的容器名称格式是:<项目名称><服务名称><序号>
虽然可以自定义项目名称、服务名称,但是如果你想完全控制容器的命名,可以使用这个标签指定:
container_name: app
这样容器的名字就指定为 app 了。
3.2.5. depends_on
在使用 Compose 时,最大的好处就是少打启动命令,但是一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。
例如在没启动数据库容器的时候启动了应用容器,这时候应用容器会因为找不到数据库而退出,为了避免这种情况我们需要加入一个标签,就是 depends_on,这个标签解决了容器的依赖、启动先后的问题。
例如下面容器会先启动 redis 和 db 两个服务,最后才启动 web 服务:
version: '2'services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres
注意的是,默认情况下使用 docker-compose up web 这样的方式启动 web 服务时,也会启动 redis 和 db 两个服务,因为在配置文件中定义了依赖关系。
3.2.6.dns
和 --dns 参数一样用途,格式如下:
dns: 8.8.8.8
也可以是一个列表:
dns: - 8.8.8.8 - 9.9.9.9
此外 dns_search 的配置也类似:
dns_search: example.comdns_search: - dc1.example.com - dc2.example.com
3.2.7. environment
和 arg 有几分类似,这个标签的作用是设置镜像变量,它可以保存变量到镜像里面,也就是说启动的容器也会包含这些变量设置,这是与 arg 最大的不同。
一般 arg 标签的变量仅用在构建过程中。而 environment 和 Dockerfile 中的 ENV 指令一样会把变量一直保存在镜像、容器中,类似 docker run -e 的效果。
environment: RACK_ENV: development SHOW: 'true' SESSION_SECRET: environment: - RACK_ENV=development - SHOW=true - SESSION_SECRET
3.2.8. extra_hosts
添加主机名的标签,就是往/etc/hosts文件中添加一些记录,与Docker client的--add-host类似:
extra_hosts: - "somehost:162.242.195.82" - "otherhost:50.31.209.229"
启动之后查看容器内部hosts:
162.242.195.82 somehost 50.31.209.229 otherhost
3.2.9. labels
向容器添加元数据,和Dockerfile的LABEL指令一个意思,格式如下:
labels: com.example.description: "Accounting webapp" com.example.department: "Finance" com.example.label-with-empty-value: ""labels: - "com.example.description=Accounting webapp" - "com.example.department=Finance" - "com.example.label-with-empty-value"
3.2.10 links
还记得上面的depends_on吧,那个标签解决的是启动顺序问题,这个标签解决的是容器连接问题,与Docker client的--link一样效果,会连接到其它服务中的容器。
格式如下:
links: - db - db:database - redis
使用的别名将会自动在服务容器中的/etc/hosts里创建。例如:
172.12.2.186 db172.12.2.186 database172.12.2.187 redis
相应的环境变量也将被创建。
3.2.11 ports
映射端口的标签。
使用HOST:CONTAINER格式或者只是指定容器的端口,宿主机会随机映射端口。
ports: - "3000" - "8000:8000" - "49100:22" - "127.0.0.1:8001:8001"
注意:当使用HOST:CONTAINER格式来映射端口时,如果你使用的容器端口小于60你可能会得到错误得结果,因为YAML将会解析xx:yy这种数字格式为60进制。所以建议采用字符串格式。
3.2.12. volumes
挂载一个目录或者一个已存在的数据卷容器,可以直接使用 [HOST:CONTAINER] 这样的格式,或者使用 [HOST:CONTAINER:ro] 这样的格式,后者对于容器来说,数据卷是只读的,这样可以有效保护宿主机的文件系统。
Compose的数据卷指定路径可以是相对路径,使用 . 或者 .. 来指定相对目录。
数据卷的格式可以是下面多种形式:
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。
volume_driver: mydriver
3.2.13. networks
加入指定网络,格式如下:
services: some-service: networks: - some-network - other-network
关于这个标签还有一个特别的子标签aliases,这是一个用来设置服务别名的标签,例如:
services: some-service: networks: some-network: aliases: - alias1 - alias3 other-network: aliases: - alias2
相同的服务可以在不同的网络有不同的别名。
3.2.14. network_mode
网络模式,与Docker client的--net参数类似,只是相对多了一个service:[service name] 的格式。
例如:
network_mode: "bridge"network_mode: "host"network_mode: "none"network_mode: "service:[service name]"network_mode: "container:[container name/id]"
可以指定使用服务或者容器的网络。
4. 常用命令
docker-compose常用命令可以通过以下命令大致看一下:
docker-compose --help
结果如下:
Define and run multi-container applications with Docker. Usage: docker-compose [-f <arg>...] [options] [COMMAND] [ARGS...] docker-compose -h|--helpOptions: -f, --file FILE Specify an alternate compose file (default: docker-compose.yml) -p, --project-name NAME Specify an alternate project name (default: directory name) --verbose Show more output --log-level LEVEL Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL) --no-ansi Do not print ANSI control characters -v, --version Print version and exit -H, --host HOST Daemon socket to connect to --tls Use TLS; implied by --tlsverify --tlscacert CA_PATH Trust certs signed only by this CA --tlscert CLIENT_CERT_PATH Path to TLS certificate file --tlskey TLS_KEY_PATH Path to TLS key file --tlsverify Use TLS and verify the remote --skip-hostname-check Don't check the daemon's hostname against the name specified in the client certificate --project-directory PATH Specify an alternate working directory (default: the path of the Compose file) --compatibility If set, Compose will attempt to convert deploy keys in v3 files to their non-Swarm equivalent Commands: build Build or rebuild services bundle Generate a Docker bundle from the Compose file config Validate and view the Compose file create Create services down Stop and remove containers, networks, images, and volumes events Receive real time events from containers exec Execute a command in a running container help Get help on a command images List images kill Kill containers 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
下面会针对一些比较常用的命令进行简单介绍
4.1. build
当修改dockerfile或者docker-compose时,运行docker-compose build 重建镜像。 生成镜像后,可使用docker-compose up启动
4.2. ps
显示所有容器信息,默认显示name、command、state、ports。
4.3. kill
强制停止某个正在运行的服务
4.4. logs
打印服务日志
语法:
logs [options] [SERVICE...]
参数:
--no-color Produce monochrome output. -f, --follow Follow log output -t, --timestamps Show timestamps --tail="all" Number of lines to show from the end of the logs for each container.
4.5. up
构建,(重新)创建,启动,链接一个服务相关的容器。链接的服务都将会启动,除非他们已经运行。默认情况, docker-compose up
将会整合所有容器的输出,并且退出时,所有容器将会停止。如果使用 docker-compose up -d
,将会在后台启动并运行所有的容器。
默认情况,如果该服务的容器已经存在, docker-compose up
将会停止并尝试重新创建他们(保持使用 volumes-from
挂载的卷),以保证 docker-compose.yml的修改生效。如果你不想容器被停止并重新创建,可以使用 docker-compose up --no-recreate
。如果需要的话,这样将会启动已经停止的容器。
语法:
up [options] [--scale SERVICE=NUM...] [SERVICE...]
参数:
-d 后台运行,输出容器的名字. Incompatible with --abort-on-container-exit. --no-color 单色输出. --no-deps 不启动link服务. --force-recreate 强制重新创建compose服务,即使没有任何改变。重新创建后启动容器 Incompatible with --no-recreate. --no-recreate 如果容器已经存在,不重新创建. Incompatible with --force-recreate. --no-build 不创建重启,即使镜像不存在. --build 重新创建镜像,然后生成容器. --abort-on-container-exit 任何容器停止,自动停止所有容器. Incompatible with -d. -t, --timeout TIMEOUT 超时时间. (default: 10) --remove-orphans 移除compose文件中未定义服务的容器
4.6. create
为服务创建容器.只是单纯的create,还需要使用start启动compose
语法:
create [options] [SERVICE...]
参数
--force-recreate 重新创建容器,即使他的配置和镜像没有改变,不兼容--no-recreate参数 --no-recreate 如果容器已经存在,不需要重新创建. 不兼容--force-recreate参数 --no-build 不创建镜像,即使缺失. --build 创建容器前,生成镜像
4.7. down
停止和删除容器、网络、卷、镜像,这些内容是通过docker-compose up
命令创建的. 默认值删除容器网络,可以通过指定 rmi volumes
参数删除镜像和卷。
语法:
down [options]
参数:
--rmi type 删除镜像,类型必须是: 'all': 删除compose文件中定义的所以镜像. 'local': 删除镜像名为空的镜像 -v, --volumes 删除卷 attached to containers. --remove-orphans Remove containers for services not defined in the Compose file
4.8. start
启动一个已经存在的服务容器。
4.9. stop
停止一个已经运行的容器,但不删除它。通过 docker-compose start
可以再次启动这些容器。
4.10. pause
暂停容器服务,docker-compose pause
暂停所有服务。docker-compose pause web
,暂停web服务的容器。
4.11. unpause
恢复容器服务,docker-compose unpause
恢复所有服务,docker-compose unpause web
,恢复web服务的容器。
4.12. restart
重启docker-compose.yml中定义的所有的已停止的和正在运行的服务。
4.13. rm
删除已经停止的容器,如果服务在运行,需要先docker-compose stop
停止容器,默认情况下,已挂载的volume中的数据不会被删除,可以使用docker volume ls
查看所有的volume情况。所有在容器中并未在volume中的数据将被删除。
4.14. run
在一个服务上执行一个命令.
语法:
run [options] [-v VOLUME...] [-p PORT...] [-e KEY=VAL...] [-l KEY=VALUE...] SERVICE [COMMAND] [ARGS...]
参数:
-d 后台运行,输出容器名. -e KEY=VAL 设置环境变量参数,可以使用多次 -u, --user="" 指定运行的用户 --no-deps 不启动link服务,只启动run的服务. --rm 运行后删除容器,后台运行模式除外(-d). -p, --publish=[] 开放端口 --service-ports compose文件中配置什么端口,就映射什么端口. -T 禁用TTY. -w, --workdir="" 设置工作目录
例如:
docker-compose run ubuntu ping docker.com
4.15. scale
设置同一个服务运行的容器个数。通过 service=num 的参数来设置数量。