用 Docker Compose 构建复杂应用

本文介绍Docker三剑客之一的Compose的一些基本使用方法。

docker Compose

Compose 是运行多个Docker容器的工具,可以在一个文件中定义一个多容器的应用,然后使用一条命令来启动你的应用,然后所有相关的操作都会被自动完成。使用Compose的一个比较直观的好处就是在构建一个多个容器组成的应用的时候少打Docker的命令

Compose的特性有如下几个:

  • 在单个主机上建立多个独立的环境
  • 创建容器的时候保护数据卷
  • 只有在容器改变的时候才重新创建
  • 将变量和环境结合

docker-compose.yml配置文件中,主要配置四个方面的东西:version、service、network、volumes

version 是表示Compose file的版本,与其对应的是Docker的发布版本,一般使用的version是3.0

Service

service定义构建整个应用的每一个容器,相当于给出命令docker container create的参数,然后创建相关的容器。以下是一些常用的配置标签:

image

指定构建容器的镜像名称或者镜像ID

1
2
3
4
5
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd

build

容器的构建参数配置,可以指定为一个构建上下文的路径

1
2
3
4
version: '3'
services:
webapp:
build: ./dir

command

可以使用command重写容器启动后默认执行的命令

1
2
3
command: bundle exec thin -p 3000

command: ["bundle", "exec", "thin", "-p", "3000"]

container_name

不使用默认生成的容器名称(默认是<项目名称><服务名称><序号>),自己定义名称

1
container_name: app

depends_on

配置两个容器之间的依赖关系,也决定了构建顺序

1
2
3
4
5
6
7
8
9
10
11
version: '3'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres

dns

制定DNS服务器,可以是一个单一的值也可以是一个列表

8.8.8.8
1
2
3
dns:
- 8.8.8.8
- 9.9.9.9

tmpfs

临时挂载目录到容器内

1
2
3
4
tmpfs: /run
tmpfs:
- /run
- /tmp

entrypoint

重写容器的进入点,可以是单一的值或者是list

1
2
3
4
5
6
7
8
9
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit
或者
entrypoint: /code/entrypoint.sh

environment

添加环境变量,可以用dict或者list,但是boolean值要使用单引号括起来

1
2
3
4
5
6
7
8
9
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:

environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET

expose

用于暴露指定的端口

1
2
3
expose:
- "3000"
- "8000"

ports

映射指定的端口

1
2
3
4
5
ports:
- "3000"
- "8000:8000"
- "49100:22"
- "127.0.0.1:8001:8001"

volumes

挂载主机目录或者命名卷到service的容器中,如果使用命名卷必须要在top-level中的volumes定义这个命名卷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: "3.2"
services:
web:
image: nginx:alpine
volumes:
- type: volume
source: mydata
target: /data
volume:
nocopy: true
- type: bind
source: ./static
target: /opt/app/static

db:
image: postgres:latest
volumes:
- "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
- "dbdata:/var/lib/postgresql/data"

volumes:
mydata:
dbdata:

networks

指定加入的网络,这个网络必须在top-level的Network中定义:

1
2
3
4
5
services:
some-service:
networks:
- some-network
- other-network

也可以使用ALIASES来为这个容器在不同的网络中使用不同的名字,使得其在不同的网络中可以发挥不同的作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 version: '2'

services:
web:
build: ./web
networks:
- new

worker:
build: ./worker
networks:
- legacy

db:
image: mysql
networks:
new:
aliases:
- database
legacy:
aliases:
- mysql

networks:
new:
legacy:

restart

重启配置,默认值为“no”在任何环境下都不重启,always指定其在任何时候都进行重启,on-failure只有在返回值表明是error的时候才重启

1
2
3
4
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped

Volumes

volumes是Docker应用首选的一种机制,其具体的模式可以看这里,下面这一张图表示了Volumes的三种模式的差异:

enter description here

Compose的配置文件中使用volumes定义应用中用到的数据卷容器,使得各个容器之间能够共用数据。
示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: "3"

services:
db:
image: db
volumes:
- data-volume:/var/lib/db
backup:
image: backup-service
volumes:
- data-volume:/var/lib/backup/data

volumes:
data-volume:

external

如果定义为true,表示这个数据卷已经被外部应用创建过了,使用docker-compose up构建应用的时候将不会创建这个数据卷

子命令

下面介绍一个常用的Compose子命令的用法,其中大部分命令的用法和docker的用法是一致的。

up

构建(或者重新构建)docker-compose.yml中定义的相关服务。
用法:up [options] [--scale SERVICE=NUM...] [SERVICE...]
常用启动命令:docker-compose up -d 让容器默认在后台运行

build

单独构建一个services中的容器,常用在改变一个容器的Dockerfile或者build的内容的时候,使用这个命令重新构建
用法:build [options] [--build-arg key=val...] [SERVICE...]

config

查看Compose信息,可以指定services或者volumes

create

单独创建services列表中的一个容器,常用用在需要事先进行配置的应用构造场景中

down

停止并删除一个contains , networks 或者volumes

exec

相当于docker exec,在指定的容器中运行命令
用法:exec [options] SERVICE COMMAND [ARGS...]

pause

暂停正在运行的service,使用docker-compose unpause恢复

logs

展示service的输出日志

pull

拉取一个在docker-compose.yml中关联的镜像到本地,但是不运行

push

docker push,只不过push的是一个servi的image

restart

重启所有停止的或者正在运行的service,如果你改变了你的docker-compose.yml 配置文件,使用这个命令之后配置将不会更新

rm

删除已经停止的容器