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
轉載請注明出處。