怎样解决 Docker 容器服务之间的依赖关系
应用场景
当使用 docker-compose 对容器进行编排时,如果服务之间存在依赖关系,compose 本身只能指定容器启动(start)的顺序,而不能左右容器之间服务就绪(ready)的先后。
dockerize
是一种用来简化在容器内运行应用的工具。它有几种功能:
- 当容器启动时,可以从模版或环境变量生成应用配置文件。
- 将日志文件重定向到标准输出。
- 在启动主进程之前,通过 TCP、HTTP(S)、套接字等协议来等待其他服务可用。
这里,我们应用的是上述第三种功能。例如
dockerize -wait tcp://db:5432 -wait http://web:80 -wait file:///tmp/generated-file
重要参数(参数):
在 docker-compose.yml 中的使用示例
重要:在这之前,首先要保证镜像构建过程中加入了 dockerize
。
version: '3.6'
services:
your-service:
# 省略了一些参数
command: sh -c "dockerize -wait tcp://mysql:3306 -timeout 300s -wait-retry-interval 30s /sayhello"
简单来说,dockerize 就是一个包装器。dockerize our_normal_command
就是调用了我们的 our_normal_command
命令。只不过可以通过指定参数来达到延时执行、使用配置文件模版和重定向文件到标准输出等一些目的。
更多使用详情请参见下方 Ref#1 和 dockerize 仓库。
使用 docker-compose-wait
工具也需要保证将其加入镜像中。
注意:其仓库预编译的二进制名称为 wait
。
在 docker-compose.yml 中的使用示例
version: '3.6'
services:
your-service:
# 省略了一些参数
command: sh -c "/wait && /sayhello"
environment:
- WAIT_HOSTS=mysql:3306
- WAIT_HOSTS_TIMEOUT=300
- WAIT_SLEEP_INTERVAL=30
- WAIT_HOST_CONNECT_TIMEOUT=30
和 dockerize
达到的效果一样,不同之处在于,wait
是通过容器运行的环境变量来控制参数的。
参数(配置项)说明
dockerize
和 docker-compose-wait
对比
- 就等待延时来说,两者都支持等待其他服务就绪后启动。后者支持干等(即仅延时启动,不依赖其他条件),前者不支持。
- 就等待判定来说,两者都支持 TCP 协议。前者支持的协议更多些,其中包括本地套接字,更加灵活,而后者仅支持 TCP 协议。
- 附加功能。前者支持文件重定向和配置文件模版,后者不具备额外功能。
其他工具
另外,还有与 docker-compose-wait
相似功能的 shell 脚本 wait-for-it.sh
。 使用示例可参见下方 Ref#3。
Control startup and shutdown order in Compose | Docker Documentation
Docker 文档中对于“启动顺序”和“容器就绪”这两点解释得非常清楚了。链接见下方 Ref#4。
文档表明,最佳解决方案是在应用代码中执行检查,在应用启动时和因某种原因失去连接时。
如果不需要应用级别的检测,可以通过包装器脚本来实现。
使用前文提到的 wait-for-it
、dockerize
和 wait-for
脚本之类的工具。
这些包装器脚本的实质就是在应用容器中不断发起 TCP 连接轮询来到检测目标服务可用的目的。这种方案的局限性就是无法验证服务真正可用的时机。
定制自己的检测脚本。
此种方式的优点是,不但能检测到端口是开放状态,而且通过客户端确定服务是切实可用的。
自己的一点思考:文档中虽然没提,但我认为这种方案是有缺点的。把每个要检测的服务对应的客户端工具打包进容器不太现实,应用程序中连接服务使用的都是特定编程语言的驱动,直接使用 binary 的情况非常罕见,这些 binary 对我们的应用没有用处,还会增大镜像的体积,使得镜像不那么纯粹。如果不打包客户端 binary 进镜像的话,只能使用 curl
之类的来轮询端口状态,又是一个自造轮子的 wait-for-it.sh 罢了。
Rerferences
- Docker Compose Wait for Dependencies : Excellent Examples - Datanovia.
- Compose file version 3 reference | Docker Documentation.
- Docker-compose: wait for container X before starting Y | Mario Buonomo.
- Control startup and shutdown order in Compose | Docker Documentation.
- Can this work with v3 of docker compose? · Issue #3 · peter-evans/docker-compose-healthcheck.
- Docker Compose wait for container X before starting Y - Stack Overflow.