docker compose 服务启动顺序控制
概要
docker-compose 可以方便组合多个 docker 容器服务, 但是, 当容器服务之间存在依赖关系时, docker-compose 并不能保证服务的启动顺序.
docker-compose 中的 depends_on 配置是容器的启动顺序, 并不是容器中服务的启动顺序.
问题重现
首先, 我们构造一个示例, 来演示 docker-compose 带来的问题. docker-compose.yml 文件如下:
version: '2'
services:
web:
image: ubuntu:14.04
depends_on:
- web
command: nc -z database 3306
database:
image: ubuntu:14.04
command: >
/bin/bash -c '
sleep 5;
echo "sleep over";
nc -lk 0.0.0.0 3306;
'
启动后, 可以发现, 确实是先启动 database, 后启动 web, 但是 database 中的服务是在大约 5 秒后才完成的, 所以导致 web 的启动失败.
$ docker-compose up
Creating tmp_database_1 ... done
Creating tmp_database_1 ...
Creating tmp_web_1 ... done
Attaching to tmp_database_1, tmp_web_1
tmp_web_1 exited with code 1
database_1 | sleep over
问题解决方式 1.0
修改 web 的启动脚本, 等待 database 的端口通了之后再启动服务
version: '2'
services:
web:
image: ubuntu:14.04
depends_on:
- database
command: >
/bin/bash -c '
while ! nc -z database 3306;
do
echo "wait for database";
sleep 1;
done;
echo "database is ready!";
echo "start web service here";
'
database:
image: ubuntu:14.04
command: >
/bin/bash -c '
sleep 5;
echo "sleep over";
nc -lk 0.0.0.0 3306;
'
再次启动,
$ docker-compose up
Creating tmp_database_1 ... done
Creating tmp_database_1 ...
Creating tmp_web_1 ... done
Attaching to tmp_database_1, tmp_web_1
web_1 | wait for database
web_1 | wait for database
web_1 | wait for database
web_1 | wait for database
web_1 | wait for database
database_1 | sleep over
web_1 | database is ready!
web_1 | start web service here
tmp_web_1 exited with code 0
web 会在 database 启动完成, 端口通了之后才启动.
问题解决方式 2.0
上面的解决方式虽然能够解决问题, 但是在 yaml 中直接插入脚本不好维护, 也容易出错. 如果有多个依赖, 或者多层依赖的时候, 复杂度会直线上升.
所以, 要封装一个 entrypoint.sh 脚本, 可以接受启动命令, 以及需要等待的服务和端口. 脚本内容如下:
#!/bin/bash
#set -x
#******************************************************************************
# @file : entrypoint.sh
# @author : wangyubin
# @date : 2018-08- 1 10:18:43
#
# @brief : entry point for manage service start order
# history : init
#******************************************************************************
: ${SLEEP_SECOND:=2}
wait_for() {
echo Waiting for $1 to listen on $2...
while ! nc -z $1 $2; do echo waiting...; sleep $SLEEP_SECOND; done
}
declare DEPENDS
declare CMD
while getopts "d:c:" arg
do
case $arg in
d)
DEPENDS=$OPTARG
;;
c)
CMD=$OPTARG
;;
?)
echo "unkonw argument"
exit 1
;;
esac
done
for var in ${DEPENDS//,/ }
do
host=${var%:*}
port=${var#*:}
wait_for $host $port
done
eval $CMD
这个脚本有 2 个参数, -d 需要等待的服务和端口, -c 等待的服务和端口启动之后, 自己的启动命令
修改 docker-compose.yml, 使用 entrypoint.sh 脚本来控制启动顺序.
version: '2'
services:
web:
image: ubuntu:14.04
depends_on:
- database
volumes:
- "./entrypoint.sh:/entrypoint.sh"
entrypoint: /entrypoint.sh -d database:3306 -c 'echo "start web service here"';
database:
image: ubuntu:14.04
command: >
/bin/bash -c '
sleep 5;
echo "sleep over";
nc -lk 0.0.0.0 3306;
'
实际使用中, 也可以将 entrypoint.sh 打包到发布的镜像之中, 不用通过 volumes 配置来加载 entrypoint.sh 脚本.
测试结果如下:
$ docker-compose up
Starting tmp_database_1 ... done
Starting tmp_web_1 ... done
Attaching to tmp_database_1, tmp_web_1
web_1 | Waiting for database to listen on 3306...
web_1 | waiting...
web_1 | waiting...
web_1 | waiting...
database_1 | sleep over
web_1 | start web service here
tmp_web_1 exited with code 0
补充
依赖多个服务和端口
使用上面的 entrypoint.sh 脚本, 也可以依赖多个服务和端口, -d 参数后面的多个服务和端口用逗号(,)隔开.
version: '2'
services:
web:
image: ubuntu:14.04
depends_on:
- mysql
- postgresql
volumes:
- "./entrypoint.sh:/entrypoint.sh"
entrypoint: /entrypoint.sh -d mysql:3306,postgresql:5432 -c 'echo "start web service here"';
mysql:
image: ubuntu:14.04
command: >
/bin/bash -c '
sleep 4;
echo "sleep over";
nc -lk 0.0.0.0 3306;
'
postgresql:
image: ubuntu:14.04
command: >
/bin/bash -c '
sleep 8;
echo "sleep over";
nc -lk 0.0.0.0 5432;
'
执行的效果可以自行尝试.
尝试间隔的配置
每次尝试连接的等待时间可以通过 环境变量 SLEEP_SECOND 来配置, 默认 2 秒 下面的配置等待时间设置为 4 秒, 就会每隔 4 秒才去尝试 mysql 服务时候可连接.
version: '2'
services:
web:
image: ubuntu:14.04
environment:
SLEEP_SECOND: 4
depends_on:
- mysql
volumes:
- "./entrypoint.sh:/entrypoint.sh"
entrypoint: /entrypoint.sh -d mysql:3306 'echo "start web service here"';
mysql:
image: ubuntu:14.04
command: >
/bin/bash -c '
sleep 4;
echo "sleep over";
nc -lk 0.0.0.0 3306;
'
docker compose 服务启动顺序控制的更多相关文章
- 构建Docker Compose服务堆栈
1.安装了docker-compose,现在我们要使用docker-compose来运行容器栈.这个地方会有两个容器,一个容器中使用Flask搭建的简单应用,另一个容器是Redis,Flash会向re ...
- 控制Docker Compose的启动顺序的一个思路
起源 守护进程daemon 从守护进程的角度看Docker Compose Docker的解决方案 思路 代码 结果 起源 Docker Compose提供了一个depends_on参数. https ...
- Docker | 第七章:Docker Compose服务编排介绍及使用
前言 前面章节,我们学习了如何构建自己的镜像文件,如何保存自己的镜像文件.大多都是一个镜像启动.当一个系统需要多个子系统进行配合时,若每个子系统也就是镜像需要一个个手动启动和停止的话,那估计实施人员也 ...
- Docker Registry服务启动过程浅析
当我们pull一个registry镜像或者自己制作一个镜像之后,使用命令docker run -d -p 5000:5000 registry,就可以启动一个私有容器服务,那么究竟是怎么做到的呢? 首 ...
- asp.net core容器&mysql容器network互联 & docker compose方式编排启动多个容器
文章简介 asp.net core webapi容器与Mysql容器互联(network方式) docker compose方式编排启动多个容器 asp.net core webapi容器与Mysql ...
- 5种常见的Docker Compose错误
在构建一个容器化应用程序时,开发人员需要一种方法来引导他们正在使用的容器去测试其代码.虽然有几种方法可以做到这一点,但 Docker Compose 是最流行的选择之一.它让你可以轻松指定开发期间要引 ...
- docker和docker compose安装使用、入门进阶案例
一.前言 现在可谓是容器化的时代,云原生的袭来,导致go的崛起,作为一名java开发,现在慌得一批.作为知识储备,小编也是一直学关于docker的东西,还有一些持续继承jenkins. 提到docke ...
- 在Ubuntu14.04系统POWER8服务器上搭建Docker Registry服务
本文描述了如何在POWER8服务器上搭建一个本地化的Docker镜像仓库,主要涉及镜像制作,Docker Registry服务启动等.希望能够对在非X86服务器上搭建Docker仓库的同学提供参考. ...
- Docker系列教程26-Docker Compose控制服务启动顺序
作者:周立 在生产中,往往有严格控制服务启动顺序的需求.然而Docker Compose自身并不具备该能力.要想实现启动顺序的控制,Docker Compose建议我们使用: wait-for-it ...
随机推荐
- 【烂笔头】adb命令篇
1.一个自动安装SystemUI.apk的脚本文件push-SystemUI.bat: adb rootadb remountadb push ./SystemUI.apk system/priv-a ...
- Numpy 基础学习
numpy.array() 功能:创建一个数据 vector = numpy.array([1,2,3,4]) matrix = numpy.array([1,2,3,4],[11,12,13,14] ...
- reStructuredText的学习
reStructruedText的学习相比makedown语法更多一些. 需要学习的也是比较多的.我整理了下.把笔记放到readthedoc上,也是方便大家学习和理解. 预览图: reStructur ...
- 我是这样理解HTTP和HTTPS区别的
为何要用https? http协议的缺点 通信使用明文,内容可能被窃听(重要密码泄露) 不验证通信方身份,有可能遭遇伪装(跨站点请求伪造) 无法证明报文的完整性,有可能已遭篡改(运营商劫持) 用htt ...
- SpringBoot基础系列-SpringBoot配置
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9990680.html SpringBoot基础系列-SpringBoot配置 概述 属性 ...
- python数据包之利器scapy用法!
scapy介绍: 在python中可以通过scapy这个库轻松实现构造数据包.发送数据包.分析数据包,为网络编程之利器! scapy安装: pip install scapy ======> ...
- 实现PHP内部的通知机制,如当一个类的属性发生变化时,另外一个类就可以收到通知
设计模式:观察者模式 当一个对象的状态发生改变时,依赖他的对象会全部收到通知,并自动更新. 使用场景 一个事件发生后,要执行一连串更新操作.传统的编程方式,就是在事件的代码之后直接加入处理逻辑,当更新 ...
- 老王说JavaDoc
开场白说点东西: { 抓住客户的痛点.痒点.爽点,提出我们产品的核心价值. 产品定位 技术架构 以微服务为核心的前后端分离,业务积木装配式技术架构.传感器采集,物联网+互联网转换,大数据分布式.存储. ...
- 解决: 移动端经mouseover显示出的弹层中链接点击问题
通常我们会遇到这样的需求,导航菜单在鼠标划过的时候显示自定义弹层,在弹层中有一些链接需要点击后跳转或者其他一些事件.比如: $(".menu li").on("mouse ...
- 博弈论进阶之Every-SG
Every-SG 给定一张无向图,上面有一些棋子,两个顶尖聪明的人在做游戏,每人每次必须将可以移动的棋子进行移动,不能移动的人输 博弈分析 题目中的要求实际是"不论前面输与否,只要最后一个棋 ...