博客详情

docker-compose编排的容器启动顺序问题 (原创)

作者: 朝如青丝暮成雪
发布时间:2019-12-23 22:59:46  文章分类:docker   阅读(3639)  评论(0)

在上一篇中,我们展示了一个基本由docker-composer编排的案例,然而那个案例却有个隐藏的问题:

虽然,我们在myapp服务中指明了依赖于redis服务 ,也就是所docker-compose能够确保容器的启动顺序是先启动redis再启动nodejs,然而容器的启动顺序并不是服务的启动顺序。

假想一下,如果我们的后端服务不是redis,而是一个启动耗时较长的后端应用,compose启动后端容器后,立即就去启动nodejs容器。很可能的结果是nodejs容器启动完成了,但是后端的容器还未到达就绪状态。这时,我们需要一种机制,判断后端容器的就绪状态(如端口是否能连通),只有当后端容器可用后,我们再启动前端容器。


优化方案一: 使用wait-for-it.sh 脚本,延迟启动容器

vi wait-for-it.sh  ,内容如下:


#!/bin/sh

TIMEOUT=15
QUIET=0

echoerr() {
  if [ "$QUIET" -ne 1 ]; then printf "%s\n" "$*" 1>&2; fi
}

usage() {
  exitcode="$1"
  cat << USAGE >&2
Usage:
  $cmdname host:port [-t timeout] [-- command args]
  -q | --quiet                        Do not output any status messages
  -t TIMEOUT | --timeout=timeout      Timeout in seconds, zero for no timeout
  -- COMMAND ARGS                     Execute command with args after the test finishes
USAGE
  exit "$exitcode"
}

wait_for() {
  for i in `seq $TIMEOUT` ; do
    nc -z "$HOST" "$PORT" > /dev/null 2>&1

    result=$?
    if [ $result -eq 0 ] ; then
      if [ $# -gt 0 ] ; then
        exec "$@"
      fi
      exit 0
    fi
    sleep 1
  done
  echo "Operation timed out" >&2
  exit 1
}

while [ $# -gt 0 ]
do
  case "$1" in
    *:* )
    HOST=$(printf "%s\n" "$1"| cut -d : -f 1)
    PORT=$(printf "%s\n" "$1"| cut -d : -f 2)
    shift 1
    ;;
    -q | --quiet)
    QUIET=1
    shift 1
    ;;
    -t)
    TIMEOUT="$2"
    if [ "$TIMEOUT" = "" ]; then break; fi
    shift 2
    ;;
    --timeout=*)
    TIMEOUT="${1#*=}"
    shift 1
    ;;
    --)
    shift
    break
    ;;
    --help)
    usage 0
    ;;
    *)
    echoerr "Unknown argument: $1"
    usage 1
    ;;
  esac
done

if [ "$HOST" = "" -o "$PORT" = "" ]; then
  echoerr "Error: you need to provide a host and port to test."
  usage 2
fi

wait_for "$@"


修改docker-compose.yml文件,


version: '3'
services:
  myapp:
    build:
     context: .
     dockerfile: myapp.dockerfile
    ports:
      - "3000:3000"
    volumes:
      - "./wait-for-it.sh:/wait-for-it.sh"
    #links:
    #  - redis 
    depends_on:
      - redis
    entrypoint: sh /wait-for-it.sh redis:6379 -t 5  --
    command: node /myapp/app.js
  redis:
    image: "redis:4-alpine"



wait-for-it.sh脚本的使用,检测依赖的[主机]:[端口]是否可用 ,  -t 指定检测的超时时间,默认15秒。  "--" 后跟的是检测通过后所执行的命令。上例中,会将command作为参数

传递给entrypoint指令。 



二、优化方案二:使用entrypoint.sh脚本,延迟容器启动

vi entrypoint.sh ,内容如下:


#!/bin/bash
#set -x
#******************************************************************************
# @file    : entrypoint.sh
# @author  : simon
# @date    : 2018-08-28 15: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

DEPENDS=''
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


修改docker-compose.yml文件,


version: '3'
services:
  myapp:
    build:
     context: .
     dockerfile: myapp.dockerfile
    ports:
      - "3000:3000"
    volumes:
      - "./entrypoint.sh:/entrypoint.sh"
    #links:
    #  - redis 
    depends_on:
      - redis
    #entrypoint:  
    command: sh /entrypoint.sh  -d 'redis:6379' -c 'node /myapp/app.js'
  redis:
    image: "redis:4-alpine"


注意:

sh /entrypoint.sh  -d 'redis:6379 192.168.11.1:80' -c 'node /myapp/app.js'   这一行既可以放到entrypoint指令中,也可以放到command指令中。 

entrypoint.sh脚本的使用:   -d 引号中跟的是[主机]:[端口] ,多个以空格隔开,代表要检测的服务。当所检测的服务均可用(端口可连通),则会执行 -c 引号中的命令。

使用这个脚本,可以同时检测多个依赖项。






关键字:  docker  compose
评论信息
暂无评论
发表评论

亲,您还没有登陆,暂不能评论哦! 去 登陆 | 注册

博主信息
   
数据加载中,请稍候...
文章分类
   
数据加载中,请稍候...
阅读排行
 
数据加载中,请稍候...
评论排行
 
数据加载中,请稍候...

Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1

鄂公网安备 42011102000739号