天天看點

靈活控制Docker容器中啟動的程序

Docker容器在建立時就會設定好CMD或者ENTRYPOINT,這會固定每次容器啟動時所運作的指令或者腳本。

容器啟動的時候,如果設定好的指令或者腳本運作發生錯誤,容器是無法正常啟動的。

如何能避免這種情況呢?解決的思路有很多種。

一種是CMD或ENTRYPOINT設定為絕對不會運作失敗的程式,例如/bin/bash。如果bash都無法啟動,那到底是對這個容器做了什麼喪盡天良的操作!運作絕對不會出錯的程式後,進入容器,再手動啟動應用,退出的話直接關閉遠端的視窗。這種方式不友善。

另一種思路也類似,也是運作一個絕對不會失敗的程式或腳本,然後通過這個程式或者腳本,來啟動我們的應用。這種方式如果應用靈活,就可以很靈活的控制每次我們運作的容器要啟動那些應用。

下面我們介紹一下需要用到的工具:

1、ENTRYPOINT,在進行DockerBuild的時候可以設定ENTRYPOINT,這個參數不會被CMD所覆寫,每次啟動容器的時候都會運作。

2、bootstrap.sh,腳本詳細内容見下文。這個腳本就放在ENTRYPOINT中,負責啟動我們的應用。

3、docker run -v ,映射本機目錄到容器中,這裡是最重要的一環。根據容器啟動的過程,是會先進行映射,再運作ENTRYPOINT中制定的腳本或指令。

在這個方式中,bootstrap.sh腳本會掃描容器中的/config/init/目錄,執行其中的shell腳本,啟動應用。我們将本機的一個目錄映射為容器内部的/config/init/目錄。隻要每次修改本機目錄中的shell腳本,即可以做到每次容器啟動的時候都指定要運作的應用,是可以動态調整的。

假如我們進行了什麼操作,導緻一個應用無法啟動,那我們直接把這個應用對應的啟動腳本删了就行了。進入容器後再手動啟動這個應用,排查下問題。不至于整個容器直接起不來了,想排查都沒機會了。

具體的建構方式如下:

1、建構鏡像

FROM centos-base:latest
MAINTAINER [email protected]
ENTRYPOINT ["/config/bootstrap.sh"]
CMD ["/bin/bash"]
           

此處指定了ENTRYPOINT、CMD指令。CMD指令為bash,我們建構的鏡像一定是有bash程序的,有問題可以直接進行排查。

2、準備bootstrap.sh

在容器内部,編寫腳本,腳本内容直接複制

mkdir /config
mkdir /config/init
vi /config/bootstrap.sh
chmod  /config/bootstrap.sh
           

3、在容器内安裝supervisord

這個程序可以設定監控哪些程序是否在運作,可以作為守護程序來使用。

yum install epel-release -y
yum install supervisor -y
cp /etc/supervisor.conf /etc/supervisor.conf.bak
           

4、其他修改

順便說下,最好把容器内的時區也改了。

rm -rf /etc/localtime
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
           

5、别忘了docker commit

這樣一個可以随時控制容器内啟動哪些應用的鏡像就建構好了。

#!/bin/bash

set -e
set -u

# Supervisord default params
SUPERVISOR_PARAMS='-c /etc/supervisord.conf'


# Create directories for supervisor's UNIX socket and logs (which might be missing
# as container might start with /data mounted from another data-container).
mkdir -p /data/conf /data/run /data/logs
chmod  /data/conf /data/run /data/logs

if [ "$(ls /config/init/)" ]; then
  for init in /config/init/*.sh; do
    . $init
  done
fi


# We have TTY, so probably an interactive container...
if test -t ; then
  # Run supervisord detached...
  supervisord $SUPERVISOR_PARAMS

  # Some command(s) has been passed to container? Execute them and exit.
  # No commands provided? Run bash.
  if [[ $@ ]]; then
    eval $@
  else
    export PS1='[\u@\h : \w]\$ '
    /bin/bash
  fi

# Detached mode? Run supervisord in foreground, which will stay until container is stopped.
else
  # If some extra params were passed, execute them before.
  # @TODO It is a bit confusing that the passed command runs *before* supervisord,
  #       while in interactive mode they run *after* supervisor.
  #       Not sure about that, but maybe when any command is passed to container,
  #       it should be executed *always* after supervisord? And when the command ends,
  #       container exits as well.
  if [[ $@ ]]; then
    eval $@
  fi
  supervisord -n $SUPERVISOR_PARAMS
fi
           

/config/bootstrap.sh

轉載請注明出處。