Docker容器自定义启动顺序
分析和思路
我们在docker运维的过程中经常会遇到一个问题,我们启动一个
docker-compose.yml
文件时,虽然我们使用depends_on
属性用依赖关系定义了两个容器的启动顺序,但这个顺序仅仅是docker创建启动的顺序,而并不是在上一个容器完全启动成功的情况下启动下一个容器。
比如一个docker-compose.yml
脚本中有mysql
和依赖此mysql
的一个java
程序a
容器,虽然a
容器在mysql
启动之后启动,但还是存在a
容器启动的时候mysql
容器还在启动中,还无法提供可用的数据库连接,这就导致一个问题,a
容器此时启动异常或者失败,虽然部分有做异常情况快速失败停止程序触发docker重启机制,但也会导致a
容器多次重启。
甚至在部分服务器资源有限的情况下,多个容器同时启动,但因为数据库等容器还未启动导致其他服务多次重启互相抢占系统资源,导致数据库容器也无法正常启动,陷入死循环,甚至严重的导致docker
服务直接无响应。
为了实现上诉a
容器在mysql
容器完全启动可以提供数据库连接的情况下再启动,就需要在a
容器中加入一个逻辑来检查等待mysql
的3306端口已经打开,然后执行a
容器的启动程序语句。
在这里用到了github上的一个开源项目wait-for-it
,可以看到其中有一个shell文件wait-for-it.sh
,这个自行去github项目中下载,这里以下面的docker-compose.yml
为例:
version: '3'
services:
mysql:
restart: always
image: mysql:5.6
ports:
- "3306:3306"
env_file:
- env/mysql.env
app:
image: app:latest
restart: always
env_file:
- env/mysql.env
ports:
- 8054:8054
depends_on:
- mysql
volumes:
- ./wait-for-it.sh:/wait-for-it.sh
command: ["/wait-for-it.sh", "-t", "0", "mysql:3306", "--", "java", "-jar", "/app.jar"]
这里将wait-for-it.sh
挂载到app
容器内,然后设置执行语句command: ["/wait-for-it.sh", "-t", "0", "mysql:3306", "--", "java", "-jar", "/app.jar"]
,其中mysql:3306
代表检查mysql
容器的3306端口是否可用,-t 0
代表设置超时为0代表禁用超时功能,即wait-for-it
脚本一直等mysql服务可用之后再执行后续命令,java -jar app.jar
就是app
容器原本的java程序启动命令。
实战操作
有两个容器:AList
和AList_OCR_Server
容器,前者需要依托后者的验证码接口,故需要先启动AList_OCR_Server
容器,等待该容器9898
端口生效后,再启动AList
容器,创建docker-compose.yml
,如下:
version: '3'
services:
AList_OCR_Server:
container_name: AList_OCR_Server
restart: always
ports:
- 9898:9898
image: xhofe/ddddocr_server:main
AList:
container_name: AList
restart: always
volumes:
- /etc/alist:/opt/alist/data
- ./wait-for-it.sh:/opt/alist/wait-for-it.sh # 将本地的wait-for-it.sh挂载到容器中
ports:
- 5244:5244
environment:
- PUID=0
- PGID=0
- UMASK=022
depends_on:
- AList_OCR_Server # 等待AList_OCR_Server容器启动(但不会检查端口是否生效)
image: xhofe/alist:latest
command: # 覆盖容器启动后默认执行的命令
[
'/opt/alist/wait-for-it.sh', # 执行wait-for-it.sh脚本
'-t', # -t 0 代表禁用超时
'0',
'AList_OCR_Server:9898', # 等待AList_OCR_Server:9898生效
'--',
'/entrypoint.sh' # AList原执行命令
]
docker-compose 可以指定配置文件
docker-compose -f <FileName.yml> up -d