笔者在前文《Docker Compose 简介》和《Dcoker Compose 原理》两篇文章中分别介绍了 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: ''
services:
web:
build: .
redis:
image: "redis:latest"

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

version: ''
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: ''
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: ''
services:
proxy:
image: nginx
ports:
- "80:80"
networks:
- frantnet
webapp:
build: .
networks:
- frantnet
- endnet
redis:
image: redis
networks:
- endnet
networks:
frantnet:
endnet:

其中的 proxy 和 webapp 连接到网络 frantnet 上,webapp 和 redis 连接在了 endnet 上(请使用《Docker Compose 简介》一文中介绍的 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-get update && apt-get install iputils-ping 命令安装 ping 命令):

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

按顺序启动容器

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

version: ''
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:/data
volumes:
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: ''
services:
web:
build: .
ports:
- "5000:5000"
logging:
driver: "json-file"
options:
max-size: "200k"
max-file: ""
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: "" 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 的官方文档。

参考:
Compose file version 3 reference
Docker Compose from development to production
Networking in Compose
Control startup order in Compose
3 Docker Compose features for improving team development workflow

Docker Compose 之进阶篇的更多相关文章

  1. Docker 镜像之进阶篇

    笔者在<Docker 基础 : 镜像>一文中介绍了 docker 镜像的基本用法,本文我们来介绍 docker 镜像背后的技术原理. 什么是 docker 镜像 docker 镜像是一个只 ...

  2. Docker 网络之进阶篇

    笔者在<Docker 基础 : 网络配置>一文中简单介绍了容器网络的基本用法,当时网络的基本使用方式还处于 --link 阶段.时过境迁,随着 docker 的快速发展,其网络架构也在不断 ...

  3. docker 数据卷 ---- 进阶篇

    笔者在<Docker 基础 : 数据管理>一文中介绍了 docker 数据卷(volume) 的基本用法.随着使用的深入,笔者对 docker 数据卷的理解与认识也在不断的增强.本文将在前 ...

  4. docker和docker compose安装使用、入门进阶案例

    一.前言 现在可谓是容器化的时代,云原生的袭来,导致go的崛起,作为一名java开发,现在慌得一批.作为知识储备,小编也是一直学关于docker的东西,还有一些持续继承jenkins. 提到docke ...

  5. [第十三篇]——Docker Compose之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker Compose Compose 简介 Compose 是用于定义和运行多容器 Docker 应用程序的工具.通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务.然 ...

  6. idea 插件的使用 进阶篇

    CSDN 2016博客之星评选结果公布    [系列直播]零基础学习微信小程序!      "我的2016"主题征文活动   博客的神秘功能 idea 插件的使用 进阶篇(个人收集 ...

  7. Python之路,Day15 - Django适当进阶篇

    Python之路,Day15 - Django适当进阶篇   本节内容 学员管理系统练习 Django ORM操作进阶 用户认证 Django练习小项目:学员管理系统设计开发 带着项目需求学习是最有趣 ...

  8. .NET遇上Docker - 使用Docker Compose组织Ngnix和.NETCore运行

    本文工具准备: Docker for Windows Visual Studio 2015 与 Visual Studio Tools for Docker 或 Visual Studio 2017 ...

  9. Docker(四):Docker 三剑客之 Docker Compose

    前两篇文章我们介绍了 Dockerfile 的使用Docker(二):Dockerfile 使用介绍,我们知道使用一个 Dockerfile 模板文件可以定义一个单独的应用容器,如果需要定义多个容器就 ...

随机推荐

  1. Do-Now—团队冲刺博客三

    Do-Now-团队 冲刺博客三 作者:仇夏 前言 不知不觉我们的项目已经做了三个多礼拜了,团队冲刺博客也写到了这第三篇,看着一个基本成型的APP安装在自己的手机上,一种喜悦感油然而生.好了,现在来看看 ...

  2. 详解Session和cookie

    1.cookie 1.1. 为什么会有cookie? 由于HTTP是无状态的,服务端并不记得你之前的状态.这种设计是为了HTTP协议的方便,但是也存在一些问题.比如我们登录一个购物网站,我们需要用户登 ...

  3. lavarel5.2官方文档阅读——架构基础

    <目录> 1.请求的生命周期 2.应用的架构 3.服务提供者 4.服务容器 5.Facades外立面(从这节起,看中文版的:https://phphub.org/topics/1783) ...

  4. 远程shell脚本执行工具类

    /** * 远程shell脚本执行工具类 */public class RemoteShellExecutorUtils { private static final Logger logger = ...

  5. javabean简介

    Javabean简介 JavaBean是一个可重复使用的软件组件.实际上JavaBean是一种Java类,通过封装属性和方法成为具有某种功能或者处理某个业务的对象,简称bean.由于javabean是 ...

  6. Excel大批量数据导出

    package com.tebon.ams.util; import lombok.extern.slf4j.Slf4j;import org.apache.poi.openxml4j.excepti ...

  7. 请输入一个大于7的整数,输出小于k并且至少满足下面2个条件中的1个条件的所有正整数

    import java.util.Scanner; /** * @author:(LiberHome) * @date:Created in 2019/3/6 22:06 * @description ...

  8. c#—get,set访问器的作用

    http://blog.sina.com.cn/s/blog_82526aa60100txtx.html 有字段为啥要有属性??? 属性作用: 1.控制读和写的权限 get:读出 set:写入 2.对 ...

  9. 微信小程序开发资料

      微信开放平台:主要面向App开发者.通常是拥有成熟的应用程序后,通过开放平台将内容分享到朋友圈或发送给某个微信好友/群.例如QQ音乐分享,美图秀秀修改过的照片直接发朋友圈或聊天. 微信公众平台:强 ...

  10. MyCat-schema.xml详解

    一.概念与图示 schema.xml配置的几个术语与其关系图示: 二.schema 标签 schema 标签用于定义 MyCat 实例中的逻辑库,如: <schema name="US ...