您的当前位置:首页DockerCompose之进阶篇

DockerCompose之进阶篇

2021-07-12 来源:爱问旅游网
DockerCompose之进阶篇

笔者在前⽂《》和《》两篇⽂章中分别介绍了 docker compose 的基本概念以及实现原理。本⽂我们将继续探索 docker compose,并通过 demo 介绍⼀些主要的⽤法。

说明:本⽂的演⽰环境为 ubuntu 16.04。应⽤多个 compose 配置⽂件

docker-compose 命令默认使⽤的配置⽂件是当前⽬录中的 docker-compose.yml ⽂件,当然我们可以通过 -f 选项指定⼀个其它名称的配置⽂件,⽐如:

$ docker-compose -f docker-compose-dev.yml up

更酷的是我们可以添加多个 -f 选项,docker-compose 会⾃动合并它们,当然也会根据先后顺序把⼀些重复的配置项覆盖掉。 下⾯我们来演⽰⼀个常见的使⽤场景,先创建⼀个名称为 docker-compose-base.yml 的配置⽂件,其内容如下:

version: '3'services: web: build: . redis:

image: \"redis:latest\"

然后再创建名称为 docker-compose-dev.yml 的配置⽂件:

version: '3'services: web: ports:

- \"5000:5000\"

下⾯的命令会同时应⽤这两个配置⽂件:

$ docker-compose -f docker-compose-base.yml -f docker-compose-dev.yml config

config 命令不会执⾏真正的操作,⽽是显⽰ docker-compose 程序解析到的配置⽂件内容:

很显然,我们指定的两个配置⽂件的内容被合并了。接下来我们再来看看配置⽂件覆盖的情况。新创建⼀个名为 docker-compose-prod.yml 的配置⽂件,编辑其内容如下:

version: '3'services: web: ports:

- \"80:5000\" redis:

image: \"redis:alpine\"

然后执⾏下⾯的命令:

$ docker-compose -f docker-compose-base.yml -f docker-compose-prod.yml config

这次 docker-compose-prod.yml ⽂件中的 image 设置覆盖了 docker-compose-base.yml ⽂件中的设置,并且映射的端⼝也改成了 80:5000。就像 demo 中演⽰的那样,我们可以通过多次指定 -f 选项的⽅式配置不同的环境,并且共⽤⼀份基础的配置⽂件。

其实 docker-compse 还默认还⽀持⼀种合并、覆盖配置⽂件的写法,就是使⽤约定的⽂件名称 docker-compose.yml 和 docker-compose.override.yml。下⾯我们把 docker-compose-base.yml ⽂件改名为 docker-compose.yml,把 docker-compose-prod.yml ⽂件改名为 docker-compose.override.yml,并直接执⾏不带 -f 选项的命令:

$ docker-compose config

结果和前⾯是⼀样的,docker-compose ⾃动合并了配置⽂件 docker-compose.yml 和 docker-compose.override.yml。这种⽅式虽然省去了指定 -f 选项的⿇烦但其缺点也是很明显的,就是⽆法指定更多不同的应⽤场景。

使⽤ network

Docker 提供的 network 功能能够对容器进⾏⽹络上的隔离,下⾯的 demo 中我们创建三个 service 和两个虚拟⽹络(注意,该 demo 主要是演⽰network 的⽤法,所以笔者并没有配置 proxy service 中的 nginx):

version: '3'services: proxy:

image: nginx ports: - \"80:80\"

networks: - frantnet webapp: build: . networks: - frantnet - endnet redis:

image: redis networks: - endnetnetworks: frantnet: endnet:

其中的 proxy 和 webapp 连接到⽹络 frantnet 上,webapp 和 redis 连接在了 endnet 上(请使⽤《》⼀⽂中介绍的 web 应⽤和 Dockerfile 来创建webapp service)。请使⽤下⾯的命令来启动应⽤:

$ docker-compose -p testnet -f docker-compose-net.yml up -d

从上图我们可以看到该命令⼀共创建了两个 network 和 三个容器。然后我们检查⼀下这三个容器的⽹络连接状态。先从 testnet_webapp_1 中 ping 另外的两个容器:

因为 webapp 服务同时连接到了 frantnet 和 endnet 两个⽹络中,所以它可以同时连接这两个⽹络中的其它容器(proxy 和 redis)。接下来再看看容器proxy 和 redis 是否可以直接连通,我们从容器 testnet_redis_1 中 ping proxy(注意,执⾏这个操作前需要在容器 testnet_redis_1 中通过 apt-getupdate && apt-get install iputils-ping 命令安装 ping 命令):

⽆法从容器 testnet_redis_1 中 ping 通 proxy 容器,这也就说明我们通过不同的虚拟⽹络实现了容器⽹络之间的隔离,从⽽在最⼤程度上去保护后端⽹络的安全。

按顺序启动容器

默认情况下 compose 启动容器的顺序是不确定的,但是有些场景下我们希望能够控制容器的启动顺序,⽐如应该让运⾏数据库的程序先启动。我们可以通过 depends_on 来解决有依赖关系的容器的启动顺序问题,看下⾯的 demo:

version: '3'services: proxy:

image: nginx ports: - \"80:80\" depends_on: - webapp - redis webapp: build: .

depends_on: - redis redis:

image: redis

启动应⽤:

⽆论我们执⾏多少次这样的启动操作,这三个容器的启动顺序都是不变的。如果不应⽤ depends_on,每次执⾏ up 命令容器的启动顺序可能都是不⼀样的。

需要注意的是 depends_on 只是解决了控制容器启动顺序的问题,如果⼀个容器的启动时间⾮常长,后⾯的容器并不会等待它完成启动。如果要解决这类问题(等待容器完成启动并开始提供服务),需要使⽤ wait-for-it 等⼯具。

配置数据卷(volume)

数据卷是处理容器中的持久化数据的主要⽅式,在 compose 中我们可以通过两种⽅式来指定数据卷:

使⽤命名的数据卷

直接指定主机上的路径来创建数据卷下⾯的 demo 演⽰了这两种数据卷的配置⽅式:

version: \"3.2\"services: web:

image: nginx:alpine volumes:

- type: volume source: mydata

target: /data - type: bind

source: ./nginx/logs target: /var/log/nginx jenkins:

image: jenkins/jenkins:lts volumes:

- jenkins_home:/var/jenkins_home - mydata:/datavolumes: mydata:

jenkins_home:

在这个例⼦中我们⼀共创建了三个数据卷,分别是两个命名的数据卷 jenkins_home 和 mydata:

其中的 jenkins_home 数据卷是给 jenkins 保存数据的。如果要在多个容器之间共享数据卷,就必须在顶级的 volumes 节点中定义这个数据卷,⽐如mydata 数据卷,它被 web 和 jenkins service 共享了。⽐如我们在 web service 中的 mydata 数据卷中创建⼀个名为 hello 的⽂件,该⽂件会同时出现在 jenkins service 中:

我们还创建了⼀个 bind 类型的 volume 在当前⽬录下的 nginx/logs ⽬录下保存 nginx 的⽇志:

配置⽇志驱动

我们还可以通过 logging 节点为 service 指定⽇志驱动及其相关的选项:

version: '3'services: web: build: . ports:

- \"5000:5000\" logging:

driver: \"json-file\" options:

max-size: \"200k\" max-file: \"10\" redis:

image: \"redis:latest\"

上⾯的代码指定⽇志驱动为 json-file,存储⽇志的最⼤⽂件 size 为 200k,最多存储 10 这样⼤的⽂件。

在 compose file ⽂件中应⽤模板

从版本 3.4 开始,可以在 compose file ⽂件中使⽤ extension fields,其实我们可以简单的把它理解为可以重⽤的代码模板。模板的定义必须以 x- 开头,然后以 & 开头的字符串为模板命名,之后就可以以 * 加上模板的名称引⽤模板:

version: '3.4'x-logging:

&default-logging driver: json-file options:

max-size: \"200k\" max-file: \"10\"

services: web: build: . ports:

- \"5000:5000\"

logging: *default-logging redis:

image: \"redis:latest\" logging: *default-logging

运⾏下⾯的命令看看模板替换的情况:

$ docker-compose -p template -f docker-compose-template.yml config

上图显⽰所有对模板的引⽤都被替换成了模板的内容。

总结

Docker compose 是⼀件强有⼒的效率⼯具,本⽂只是介绍了⼀些常见的⽤法。如果你还想掌握更多内容,请参考 compose file 的官⽅⽂档。

参考:

因篇幅问题不能全部显示,请点此查看更多更全内容