Docker Compose 的配置文件采用 YAML 格式,因此有必要在正文之前简要说明下。YAML 是一门专门用来写配置文件的语言,设计目标就是方便读写,其实质上是一种通用的数据串行化格式,基本语法规则如下:
- 大小写敏感。
- 表示注释。
- 使用缩进表示层级关系。
- 缩进时不允许使用 Tab 键,只允许使用空格。
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可。
YAML 支持的数据结构有三种:
- 对象:。
- 数组:一组中划线开头的行,例如:
- 值类型和字符串。
Docker 可以极为方便地部署单个服务,但这时候我们需要一个工具来整合 Docker 的功能,使之能够更便捷地去管理整个微服务集群的部署和迁移,Docker Compose 正是应此而生。他是由 Python 编写的程序,能够根据指令结合配置文件转换成对应的 Docker API 的操作,并直接体现到 Docker Daemon 中,这就代替我们完成了重复输入复杂指令的过程,主要功能可分为以下两点:
- Service:代表的是运行同种应用程序的一个或多个相同容器的抽象定义,也是我们在Docker Compose 中配置的主要对象。在每个 Docker Compose 的配置文件中,我们可以定义多个服务,并定义服务的配置,以及服务于服务之间的以来关系。
- Project:代表的是由多个服务所组成的一个相对完整的业务单元。
安装命令:
Docker Compose 的核心就是其配置文件,采用 YAML 格式,默认为 ,参数详解可查阅“官方文档”,以下只做一个常规摘要。
services
所有服务的根节点。
image
指定服务的镜像名,若本地不存在,则 Compose 会去仓库拉取这个镜像:
ports
端口映射,例:
volumes
挂载主机目录,其中 ro 表示只读,例:
大多数情况下集群中部署的应该都是无状态服务,服务可复制且不固定在某一台宿主机,所以挂载的数据卷最好应当与宿主机脱离关系,例:
当然,这种情况下最好是优先创建数据卷,后在配置文件中引用,例:
若必须挂载集群中一台宿主机的目录作为数据卷,则要安装一个 docker 插件:
networks
配置服务间的网路互通与隔离,例:
配置服务密码访问,例:
healthcheck
健康检查,这个非常有必要,等服务准备好以后再上线,避免更新过程中出现短暂的无法访问。
其实大多数情况下健康检查的规则都会写在 Dockerfile 中:
depends_on
依赖的服务,优先启动,例:
environment & env_file
设置环境变量和指定环境变量的文件,例:
deploy
部署相关的配置都在这个节点下,例:
若非特殊服务,以上各节点的配置能够满足大部分部署场景了。
Docker 默认包含了 Swarm,因此可以直接使用,初始化命令:,此时将会默认当前节点为 Leader,以下命令为查看 token:,其他节点可以用 manager 或者 worker 的身份加入到当前集群,例:
执行 脱离集群。
以下各节点常规操作命令,比较简单,就不解释了:
- docker node demote [NODE]
- docker node inspect [NODE]
- docker node ls
- docker node promote [NODE]
- docker node ps [NODE]
- docker node rm [NODE]
- docker node update [OPTIONS] NODE
集群最擅长的就是解决多服务问题,只要在同一 network 之下,服务之间默认可以直接通过 service_name 互通有无。但为了避免混乱,各服务与外部的通信最好统一交给一个反向代理服务转发。因对 nginx 比较熟悉,所以我最初选择的代理是“jwilder/nginx-proxy”:
负载均衡使用的是阿里云的 SLB,监听 ,这样一个服务就实现了节点检查、代理和 https 重定向为一身。拖 nginx 的福,反正用起来就是爽,点击“Nginx 原理解析和配置摘要”进一步了解。
正所谓乐极生悲,某一次我在扩展 Swarm 集群的时候提升了部分 work 节点为 manager, 并且扩展了代理的数量,这让很多服务频繁出现 503,找来找去我发现问题出在 nginx-proxy 代理上。当服务在各节点分布不均的时候,非 leader 节点上的那个代理无法找到服务,废了老大的劲儿也没找到合理的解决方案。
最后我决定选择“Docker Flow Proxy”作为新的代理(好家伙,这一看文档吓我一跳,我还是第一次看到私人的开源项目能把参考文档写得这么详细,作者的细腻程度“令人发指”,小弟顶礼膜拜之),以下是我的案例:
更换代理的过程也并非一帆风顺,我在 https 重定向这个问题浪费了好多时间,最后也没在代理中解决。作者当然是考虑到了这个问题,经典的解决方案应如下:
但奈何哥哥“非经典”呀,我的 https 证书和负载均衡都委托给阿里云的 SLB 了,SLB 代理的后端请求只能限定 http。我的想法还是监听所有请求 443 端口的域名并返回 301,但以下方案并没有成功:
除了代理,最好再加一个监控服务,我选择了官方案例中的 visualizer ,配合 proxy 示例:
docker stack
部署命令:,私有仓库必须加 才能下载镜像。除此之外常用的如下:
docker service
我使用 Compose 的场景一般都结合 Swarm,因此很少去记手动创建或者更改配置的命令了,意义也不大。除了查看移除等与上文相似以外,此处还应记两个:
分别是查看日志和服务异常后强制重启。
到此为止写了蛮多了,其余还有一些比较重要内容的后续有空再整理一篇。总结一下,开头我放的那张图其实很形象:Docker 可以看做集装箱把杂乱的货物一个个整理归类, Compose 则是用于编排这些集装箱,最后 Swarm 就是多提供几条船,挂掉一两条还能继续走,提高稳定性。
不知为何此刻我会突然想到一句诗:“天苍苍野茫茫风吹草低见牛羊”,有关联吗?没关联,想到就写了,晚安:)