一 介绍
1 简介
compose是一个定义和运行多容器的docker应用的工具。compose 通过yaml文件配置应用服务,然后使用docker-compose脚本来启动,停止和重启应用,和应用中的服务以及所有依赖服务的容器。使用Docker Compose不再需要使用shell脚本来启动容器,非常适合组合使用多个容器进行开发的场景。
关于docker-compose的常用命令,请看我另一篇文章
2 Compose和Docker兼容性
compose文件格式版本 | docker版本 |
---|---|
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.3 | 17.06.0+ |
2.2 | 1.13.0+ |
2.1 | 1.12.0+ |
2.0 | 1.10.0+ |
1.0 | 1.9.1.+ |
Docker版本变化说明:
Docker从1.13.x版本开始,版本分为企业版EE和社区版CE,版本号也改为按照时间线来发布,比如17.03就是2017年3月。
Docker的linux发行版的软件仓库从以前的https://apt.dockerproject.org和https://yum.dockerproject.org变更为目前的https://download.docker.com, 软件包名字改为docker-ce和docker-ee。
二 安装
需要先安装docker,详见我另一篇博客
两种最新的docker安装方式
1 从github上下载docker-compose二进制文件安装
# 下载最新compose版本
[root@slave1 ~]# curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 664 100 664 0 0 604 0 0:00:01 0:00:01 --:--:-- 604
100 10.3M 100 10.3M 0 0 3404k 0 0:00:03 0:00:03 --:--:-- 8896k
[root@slave1 ~]# ll /usr/local/bin/docker-compose
-rw-r--r-- 1 root root 10858808 Dec 23 21:50 /usr/local/bin/docker-compose
# 版本发布地址:https://github.com/docker/compose/releases
# 若是github访问太慢,可以用daocloud下载,命令如下
# curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 添加执行权限
[root@slave1 ~]# chmod +x /usr/local/bin/docker-compose
# 命令补全工具(此步骤可选)
# 具体参考:https://docs.docker.com/compose/completion/
[root@slave1 ~]# curl -L https://raw.githubusercontent.com/docker/compose/1.21.2/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
# 测试安装结果
[root@slave1 ~]# docker-compose --version
docker-compose version 1.21.2, build a133471
2 pip安装
pip install docker-compose
三 docker-compose文件结构和示例
1 docker-compose文件结构
docker-compose.yml:
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:
四 docker-compose使用示例
通过docker-compose构建一个在docker中运行的基于python flask框架的web应用
注意:确保你已经安装了Docker Engine和Docker Compose。 您不需要安装Python或Redis,因为这两个都是由Docker镜像提供的。
1 定义python应用
(1)创建工程目录
[root@slave1 ~]# mkdir compose_test
[root@slave1 ~]# cd compose_test/
[root@slave1 compose_test]# mkdir src
[root@slave1 compose_test]# mkdir docker
# 结构如下
└── compose_test
├── docker
│ └── docker-compose.yml
├── Dockerfile
└── src
├── app.py
└── requirements.txt
(2)在compose_test/src/目录下创建python flask应用 compose_test/src/app.py文件
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
return 'Hello World! I have been seen {} times.\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
(3)创建python 需求文件 compose_test/src/requirements.txt
flask
redis
2 创建容器的Dockerfile文件
一个容器一个Dockerfile文件,在compose_test/目录中创建Dockerfile文件
[root@slave1 compose_test]# vim Dockerfile
FROM python:3.7
COPY src/ /opt/src
WORKDIR /opt/src
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
Dockerfile文件告诉docker了如下信息:
从Python 3.7的镜像开始构建一个容器镜像。
复制src(即compose_test/src)目录到容器中的/opt/src目录。
将容器的工作目录设置为/opt/src(通过docker exec -it your_docker_container_id_or_name bash 进入容器后的默认目录)。
安装Python依赖关系。
将容器的默认命令设置为python app.py。
3 定义docker-compose脚本
在compose_test/docker/目录下创建docker-compose.yml文件,并在里面定义服务,内容如下
version: '3'
services:
web:
build: ../
ports:
- "5000:5000"
redis:
image: redis:3.0.7
这个compose文件定义了两个服务,即定义了web和redis两个容器。
web容器:
- 使用当前docker-compose.yml文件所在目录的上级目录(compose_test/Dockerfile)中的Dockerfile构建映像。
- 将容器上的暴露端口5000映射到主机上的端口5000。 我们使用Flask Web服务器的默认端口5000。
redis容器:
- redis服务使用从Docker Hub提取的官方redis镜像3.0.7版本。
4 使用Compose构建并运行您的应用程序
在compose_test/docker/目录下执行docker-compose.yml文件:
# 执行
[root@slave1 docker]# docker-compose up
# 若是要后台运行: $ docker-compose up -d
# 若不使用默认的docker-compose.yml 文件名
Creating network "docker_default" with the default driver
# 可以看到在构建容器
Building web
Step 1/5 : FROM python:3.7
3.7: Pulling from library/python
0e29546d541c: Pull complete
9b829c73b52b: Pull complete
cb5b7ae36172: Pull complete
6494e4811622: Pull complete
6f9f74896dfa: Pull complete
fcb6d5f7c986: Pull complete
7a72d131c196: Pull complete
c4221d178521: Pull complete
71d5c5b5a91f: Pull complete
Digest: sha256:d9abbc0737ff8d23a546859c85903f1b8235a1495a405d5a47cbc55747f27b20
Status: Downloaded newer image for python:3.7
---> ad37de9b03ef
Step 2/5 : COPY src/ /opt/src
---> bec6e510a55c
Step 3/5 : WORKDIR /opt/src
---> Running in 6a22a02446ca
Removing intermediate container 6a22a02446ca
---> f989bf8651be
Step 4/5 : RUN pip install -r requirements.txt
---> Running in ba71ecb25cd1
Collecting flask
Downloading Flask-2.0.2-py3-none-any.whl (95 kB)
Collecting redis
Downloading redis-4.0.2-py3-none-any.whl (119 kB)
Collecting Jinja2>=3.0
Downloading Jinja2-3.0.3-py3-none-any.whl (133 kB)
Collecting itsdangerous>=2.0
Downloading itsdangerous-2.0.1-py3-none-any.whl (18 kB)
Collecting click>=7.1.2
Downloading click-8.0.3-py3-none-any.whl (97 kB)
Collecting Werkzeug>=2.0
Downloading Werkzeug-2.0.2-py3-none-any.whl (288 kB)
Collecting deprecated
Downloading Deprecated-1.2.13-py2.py3-none-any.whl (9.6 kB)
Collecting importlib-metadata
Downloading importlib_metadata-4.10.0-py3-none-any.whl (17 kB)
Collecting MarkupSafe>=2.0
Downloading MarkupSafe-2.0.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (31 kB)
Collecting wrapt<2,>=1.10
Downloading wrapt-1.13.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (79 kB)
Collecting typing-extensions>=3.6.4
Downloading typing_extensions-4.0.1-py3-none-any.whl (22 kB)
Collecting zipp>=0.5
Downloading zipp-3.6.0-py3-none-any.whl (5.3 kB)
Installing collected packages: zipp, typing-extensions, wrapt, MarkupSafe, importlib-metadata, Werkzeug, Jinja2, itsdangerous, deprecated, click, redis, flask
Successfully installed Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 deprecated-1.2.13 flask-2.0.2 importlib-metadata-4.10.0 itsdangerous-2.0.1 redis-4.0.2 typing-extensions-4.0.1 wrapt-1.13.3 zipp-3.6.0
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.2.4; however, version 21.3.1 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.
Removing intermediate container ba71ecb25cd1
---> ea9fd92e514d
Step 5/5 : CMD ["python", "app.py"]
---> Running in 6ba733fd2108
Removing intermediate container 6ba733fd2108
---> a998c7c0d142
Successfully built a998c7c0d142
Successfully tagged docker_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Pulling redis (redis:3.0.7)...
3.0.7: Pulling from library/redis
f5cc0ee7a6f6: Pull complete
5fc25ed18e87: Pull complete
e025bc8872f6: Pull complete
77c68b51b836: Pull complete
7c403ece3755: Pull complete
0a653bd338f4: Pull complete
31531fd948c6: Pull complete
Digest: sha256:730b765df9fe96af414da64a2b67f3a5f70b8fd13a31e5096fee4807ed802e20
Status: Downloaded newer image for redis:3.0.7
Creating docker_redis_1 ...
Creating docker_web_1 ... error # 这里有个error,不慌,看看后面的详细信息
Creating docker_redis_1 ... done
0 failed: port is already allocated
ERROR: for web Cannot start service web: driver failed programming external connectivity on endpoint docker_web_1 (f7e89e227b028ebad4a1c6a9b0ec0bec5e1e54c1cad08fc6106f0dcdf176d003): Bind for 0.0.0.0:5000 failed: port is already allocated # 这里可以看到提示接口被占用
ERROR: Encountered errors while bringing up the project.
# 开始排错,查看一下哪个进程占用了端口,啊,是proxy,这个不能乱关
[root@slave1 docker]# netstat -tulnp | grep 5000
tcp 0 0 0.0.0.0:5000 0.0.0.0:* LISTEN 39651/docker-proxy
# 那就看看能不能用别的端口做实验,nice,5001没有用过
[root@slave1 docker]# netstat -tulnp | grep 5001
# 修改docker-compose.yml,将宿主机的5001端口映射出来
[root@slave1 docker]# ll
total 4
-rw-r--r-- 1 root root 107 Dec 23 23:03 docker-compose.yml
[root@slave1 docker]# vim docker-compose.yml
version: '3'
services:
web:
build: ../
ports:
- "5001:5000"
redis:
image: redis:3.0.7
# 再次执行
[root@slave1 docker]# docker-compose up
docker_redis_1 is up-to-date
Recreating docker_web_1 ... done # 容器成功启动
Attaching to docker_redis_1, docker_web_1
redis_1 | 1:C 24 Dec 04:08:26.308 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1 | _._
redis_1 | _.-``__ ''-._
redis_1 | _.-`` `. `_. ''-._ Redis 3.0.7 (00000000/0) 64 bit
redis_1 | .-`` .-```. ```\/ _.,_ ''-._
redis_1 | ( ' , .-` | `, ) Running in standalone mode
redis_1 | |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
redis_1 | | `-._ `._ / _.-' | PID: 1
redis_1 | `-._ `-._ `-./ _.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' | http://redis.io
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' |
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | `-._ `-.__.-' _.-'
redis_1 | `-._ _.-'
redis_1 | `-.__.-'
redis_1 |
redis_1 | 1:M 24 Dec 04:08:26.309 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 24 Dec 04:08:26.309 # Server started, Redis version 3.0.7
redis_1 | 1:M 24 Dec 04:08:26.309 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 24 Dec 04:08:26.309 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1 | 1:M 24 Dec 04:08:26.309 * The server is now ready to accept connections on port 6379
web_1 | * Serving Flask app 'app' (lazy loading)
web_1 | * Environment: production
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | Use a production WSGI server instead.
web_1 | * Debug mode: on
web_1 | * Running on all addresses.
web_1 | WARNING: This is a development server. Do not use it in a production deployment.
web_1 | * Running on http://172.19.0.3:5000/ (Press CTRL+C to quit)
web_1 | * Restarting with stat
web_1 | * Debugger is active!
web_1 | * Debugger PIN: 127-792-615
Ctrl C退出
然后在浏览器中输入http://0.0.0.0:5000/192.168.247.131:5001http://0.0.0.0:5000/查看运行的应用程序。
192.168.247.131是我做实验的虚拟机的地址,也就是宿主机
5 编辑compose文件以添加文件绑定挂载
上面的代码是在构建时静态复制到容器中的,即通过Dockerfile文件中的COPY src /opt/src命令实现物理主机中的源码复制到容器中,这样在后续物理主机src目录中代码的更改不会反应到容器中。
可以通过volumes 关键字实现物理主机目录挂载到容器中的功能(同时删除Dockerfile中的COPY指令,不需要创建镜像时将代码打包进镜像,而是通过volums动态挂载,容器和物理host共享数据卷):
version: '3'
services:
web:
build: ../
ports:
- "5001:5000"
volumes:
- ../src:/opt/src
redis:
image: "redis:3.0.7"
通过volumes(卷)将主机上的项目目录(compose_test/src)挂载到容器中的/opt/src目录,允许即时修改代码,而无需重新构建镜像。
6 重新构建和运行应用程序
# 静默启动
[root@slave1 docker]# docker-compose up -d
Recreating docker_web_1 ...
Recreating docker_web_1 ... done
# 查看进程中的容器验证文件同步
[root@slave1 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d5137c5b813d docker_web "python app.py" 30 seconds ago Up 30 seconds 0.0.0.0:5001->5000/tcp docker_web_1
048986efc811 redis:3.0.7 "docker-entrypoint.s…" 20 minutes ago Up 20 minutes 6379/tcp docker_redis_1
# 进入容器创建一个小文件
[root@slave1 docker]# docker exec -it d5137c5b813d /bin/bash
root@d5137c5b813d:/opt/src# pwd
/opt/src
root@d5137c5b813d:/opt/src# touch hehe
root@d5137c5b813d:/opt/src# ls
app.py hehe requirements.txt
root@d5137c5b813d:/opt/src# read escape sequence # Ctrl+P+Q退出容器
# 进入宿主机查看文件
[root@slave1 docker]# cd ../src/
[root@slave1 src]# ll
total 8
-rw-r--r-- 1 root root 311 Dec 23 22:19 app.py
-rw-r--r-- 1 root root 0 Dec 23 23:29 hehe # 自动同步
-rw-r--r-- 1 root root 12 Dec 23 22:20 requirements.txt
浏览器验证
五 compose常用服务配置参考
1 介绍
Compose文件是一个定义服务,网络和卷的YAML文件。 Compose文件的默认文件名为docker-compose.yml。也对此文件使用.yml或.yaml扩展名,都可以的。
与docker运行一样,默认情况下,Dockerfile中指定的选项(例如,CMD,EXPOSE,VOLUME,ENV)都生效,不需要在docker-compose.yml中再次指定。同时可以使用类似Bash的$ {VARIABLE} 语法在配置值中使用环境变量,有关详细信息,请参阅变量替换。
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将来会被弃用
2 版本3中服务定义支持的所有配置选项
build
build 可以指定包含构建上下文的路径
version: '2'
services:
webapp:
build: ./dir
或者,作为一个对象,该对象具有上下文路径和指定的Dockerfile文件以及args参数值:
version: '2'
services:
webapp:
build:
context: ./dir
dockerfile: Dockerfile-alternate
args:
buildno: 1
# webapp服务将会通过./dir目录下的Dockerfile-alternate文件构建容器镜像。
如果你同时指定image和build,则compose会通过build指定的目录构建容器镜像,而构建的镜像名为image中指定的镜像名和标签
build: ./dir
image: webapp:tag
# 这将由./dir构建的名为webapp和标记为tag的镜像
context
包含Dockerfile文件的目录路径,或者是git仓库的URL。
当提供的值是相对路径时,它被解释为相对于当前compose文件的位置。 该目录也是发送到Docker守护程序构建镜像的上下文。
dockerfile
备用Docker文件。Compose将使用备用文件来构建。 还必须指定构建路径。
args
添加构建镜像的参数,环境变量只能在构建过程中访问。
首先,在Dockerfile中指定要使用的参数:
ARG buildno
ARG password
RUN echo "Build number: $buildno"
RUN script-requiring-password.sh "$password"
然后在args键下指定参数。 参数可以是映射或列表:
build:
context: .
args:
buildno: 1
password: secret
build:
context: .
args:
- buildno=1
- password=secret
注意:YAML布尔值(true,false,yes,no,on,off)必须用引号括起来,以便解析器将它们解释为字符串。
image
指定启动容器的镜像,可以是镜像仓库/标签或者镜像id(或者id的前一部分)
如果镜像不存在,Compose将尝试从官方镜像仓库将其pull下来,如果你还指定了build,它将使用指定的build选项构建它,并使用image指定的名字和标记对其进行标记。
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd
container_name
指定一个自定义容器名称,而不是生成的默认名称。由于Docker容器名称必须是唯一的,因此如果指定了自定义名称,则无法将服务扩展到多个容器。
container_name: my-web-container
depends_on
在使用Compose时,最大的好处就是少打启动命令,但一般项目容器启动的顺序是有要求的,如果直接从上到下启动容器,必然会因为容器依赖问题而启动失败。例如在没启动数据库容器的时候启动应用容器,应用容器会因为找不到数据库而退出。depends_on标签用于解决容器的依赖、启动先后的问题。
version: '2'
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres
上述YAML文件定义的容器会先启动redis和db两个服务,最后才启动web 服务。
volumes
卷挂载路径设置。可以设置宿主机路径 (HOST:CONTAINER) 或加上访问模式 (HOST:CONTAINER:ro),挂载数据卷的默认权限是读写(rw),可以通过ro指定为只读。
你可以在主机上挂载相对路径,该路径将相对于当前正在使用的Compose配置文件的目录进行扩展。
相对路径应始终以“ . ”或者“ .. ”开始。
volumes:
# 只需指定一个路径,让引擎创建一个卷
- /var/lib/mysql
# 指定绝对路径映射
- /opt/data:/var/lib/mysql
# 相对于当前compose文件的相对路径
- ./cache:/tmp/cache
# 用户家目录相对路径
- ~/configs:/etc/configs/:ro
# 命名卷
- datavolume:/var/lib/mysql
如果要跨多个服务并重用挂载卷,需请在顶级volumes关键字中命名挂在卷(非强制),如下的示例亦有重用挂载卷的功能,但是不提倡:
version: "3"
services:
web1:
build: ./web/
volumes:
- ../code:/opt/web/code
web2:
build: ./web/
volumes:
- ../code:/opt/web/code
如果不使用宿主机的路径,可以指定一个volume_driver。
volume_driver: mydriver
注意:通过顶级volumes定义一个挂载卷,并从每个服务的卷列表中引用它, 这会替换早期版本的Compose文件格式中volumes_from。
volumes_from(低版本)
从另一个服务或容器挂载其数据卷:
volumes_from:
- service_name
- container_name
command
覆盖容器启动后默认执行的命令。
command: bundle exec thin -p 3000
该命令也可以是一个类似于dockerfile的列表:
command: ["bundle", "exec", "thin", "-p", "3000"]
links
链接到另一个服务中的容器。 需指定服务名称和链接别名(SERVICE:ALIAS),或者仅指定服务名称。
web:
links:
- db
- db:database
- redis
# 使用别名将会自动在服务容器中的/etc/hosts里创建
172.17.2.186 db
172.17.2.186 database
172.17.2.187 redis
在当前的web服务的容器中可以通过链接的db服务的别名database访问db容器中的数据库应用,如果没有指定别名,则可直接使用服务名访问。
链接不需要启用服务进行通信 - 默认情况下,任何服务都可以以该服务的名称到达任何其他服务。 (实际是通过设置/etc/hosts的域名解析,从而实现容器间的通信。故可以像在应用中使用localhost一样使用服务的别名链接其他容器的服务,前提是多个服务容器在一个网络中可路由联通)
links也可以起到和depends_on相似的功能,即定义服务之间的依赖关系,从而确定服务启动的顺序。
external_links
链接到docker-compose.yml 外部的容器,甚至并非 Compose 管理的容器。参数格式跟 links 类似。
external_links:
- redis_1
- project_db_1:mysql
- project_db_1:postgresql
expose
暴露端口,但不映射到宿主机,只被连接的服务访问。
仅可以指定内部端口为参数
expose:
- "3000"
- "8000"
ports
暴露端口信息。
常用的简单格式:使用宿主:容器 (HOST:CONTAINER)格式或者仅仅指定容器的端口(宿主将会随机选择端口)都可以。
注意:当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 你可能会得到错误得结果,因为 YAML 将会解析 xx:yy 这种数字格式为 60 进制。所以建议采用字符串格式。
# 简单的短格式:
ports:
- "3000"
- "3000-3005"
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"
# 在v3.2中ports的长格式的语法允许配置不能用短格式表示的附加字段。
# 长格式:
ports:
- target: 80
published: 8080
protocol: tcp
mode: host
target:容器内的端口
published:物理主机的端口
protocol:端口协议(tcp或udp)
mode:host 和ingress 两总模式,host用于在每个节点上发布主机端口,ingress 用于被负载平衡的swarm模式端口。
extra_hosts
添加主机名的标签,会在/etc/hosts文件中添加一些记录
extra_hosts:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
# 启动后查看容器内部hosts:
162.242.195.82 somehost
50.31.209.229 otherhost
restart
默认为no,在任何情况下都不会重启容器。 指定为always时,容器总是重新启动。 如果退出代码指示出现故障错误,则on-failure将重新启动容器。
restart: "no"
restart: always
restart: on-failure
restart: unless-stopped
environment
添加环境变量。
可以使用数组或字典两种形式。 (布尔值; true,false,yes,no需要用引号括起来,以确保它们不被YML解析器转换为True或False。)
只给定名称的变量会自动获取它在 Compose 主机上的值,可以用来防止泄露不必要的数据。
环境变量可以用来配置Docker-Compose的行为。 COMPOSE_PROJECT_NAME 设置通过Compose启动的每一个容器前添加的项目名称,默认是当前工作目录的名字。 COMPOSE_FILE 设置docker-compose.yml模板文件的路径,默认路径是当前工作目录。 DOCKER_HOST 设置Docker daemon的地址,默认使用unix:///var/run/docker.sock。 DOCKER_TLS_VERIFY 如果设置不为空,则与Docker daemon交互通过TLS进行。 DOCKER_CERT_PATH 配置TLS通信所需要的验证(ca.pem、cert.pem 和 key.pem)文件的路径,默认是 ~/.docker 。
environment:
RACK_ENV: development
SHOW: 'true'
SESSION_SECRET:
environment:
- RACK_ENV=development
- SHOW=true
- SESSION_SECRET
注意:如果你的服务指定了build选项,那么在构建过程中通过environment定义的环境变量将不会起作用。 将使用build的args子选项来定义构建时的环境变量。
pid
将PID模式设置为主机PID模式。 这就打开了容器与主机操作系统之间的共享PID地址空间。 打开该选项的容器可以相互通过进程 ID 来访问和操作。
pid: "host"
dns
配置 DNS 服务器。可以是一个值,也可以是一个列表。
dns: 8.8.8.8
dns:
- 8.8.8.8
- 9.9.9.9
dns_search
配置DNS搜索域。可以是一个值,也可以是一个列表
dns_search:example.com
dns_search:
- domain1.example.com
- domain2.example.com
entrypoint
在Dockerfile中有一个指令叫做ENTRYPOINT指令,用于指定接入点.在docker-compose.yml中可以定义接入点,覆盖Dockerfile中的定义
entrypoint: /code/entrypoint.sh
env_file
在docker-compose.yml中可以定义一个专门存放变量的文件。 如果通过docker-compose -f FILE指定配置文件,则env_file中路径会使用配置文件路径。 如果有变量名称与environment指令冲突,则以后者为准。格式如下:
env_file: .env
# 或者根据docker-compose.yml设置多个
env_file:
- ./common.env
- ./apps/web.env
- /opt/secrets.env
# 如果在配置文件中有build操作,变量并不会进入构建过程中。
cap_add
增加指定容器的内核能力(capacity)。
# 让容器具有所有能力可以指定
cap_add:
- ALL
cap_drop
去掉指定容器的内核能力(capacity)。
# 去掉NET_ADMIN能力可以指定:
cap_drop:
- NET_ADMIN
cgroup_parent
# 创建了一个cgroup组名称为cgroups_1:
cgroup_parent: cgroups_1
devices
指定设备映射关系
devices:
- "/dev/ttyUSB1:/dev/ttyUSB0"
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: mysql
# 后者会自动继承common.yml中的webapp服务及环境变量定义。
***
extends限制如下:
A、要避免出现循环依赖
B、extends不会继承links和volumes_from中定义的容器和数据卷资源
推荐在基础模板中只定义一些可以共享的镜像和环境变量,在扩展模板中具体指定应用变量、链接、数据卷等信息
labels
为容器添加Docker元数据(metadata)信息.
# 为容器添加辅助说明信息
labels:
com.startupteam.description: "webapp for a strtup team"
log_driver
指定日志驱动类型。目前支持三种日志驱动类型:
log_driver: "json-file"
log_driver: "syslog"
log_driver: "none"
log_opt
日志驱动的相关参数.
# 示例
log_driver: "syslog"log_opt:
syslog-address: "tcp://192.168.0.42:123"
net
设置网络模式。
net: "bridge"
net: "none"
net: "host"
security_opt
指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等)。
# 配置标签的用户名和角色名:
security_opt:
- label:user:USER
- label:role:ROLE
最后示例
# docker-compose.yaml文件如下:
version: '2'
services:
web1:
image: nginx
ports:
- "6061:80"
container_name: "web1"
networks:
- dev
web2:
image: nginx
ports:
- "6062:80"
container_name: "web2"
networks:
- dev
- pro
web3:
image: nginx
ports:
- "6063:80"
container_name: "web3"
networks:
- pro
networks:
dev:
driver: bridge
pro:
driver: bridge
#volumes:
#启动
docker-compose up -d
# 通过浏览器访问web1,web2,web3服务
http://127.0.0.1:6061
http://127.0.0.1:6062
http://127.0.0.1:6063