說下我的需求,就是在使用 docker-compose 啟動server容器后,執行命令或者執行腳本運行容器內部的進程。
容器是個基於django框架的web server,通過uwsgi啟動,我是這樣操作的:
-
1.在docker-compose.yaml文件中,在容器設置部分加入
entrypoint: /root/path/xxx.sh,另外也編輯command: bash, -
2.啟動服務,
docker-compose up -d,后台進程啟動服務, -
3.查看服務,
docker-compose ps,發現容器處於Restarting,換句話說,容器啟動有問題, -
4.先停止服務,
docker-compose stop
於是,我注釋掉docker-compose的entrypoint部分,然后docker-compose up -d,查看服務docker-compose ps,容器處於up狀態,於是我通過exec命令在容器中執行相關命令,如下圖:

可以看到uwsgi進程是起來了,本地測試web server的接口,

顯然,這與我們的初衷不符,在 docker-compose 的時候,通常希望通過docker-compose up -d起來容器后,容器內部的應用程序就起來了,如果我們還需要通過exec,這種操作未免多余。
好在,docker還有個特別之處,我們可以通過 docker build 讀取到 Dockerfile中的指令后,在構建新鏡像再起容器的時候,可以直接執行腳本文件運行容器內部應用程序,同時不退出容器。
Dockerfile的設置:
# dockerfile to build image for docker-compose
FROM xxxxx/xxxserver-ubuntu16.04:1.0
MAINTAINER xxx@google.com.cn
ENV PYTHON 2.7
ENV DJANGO 1.11.5
LABEL version=1.1
WORKDIR /opt/big_factory/xxxserver
EXPOSE 9443
# 此處設置ENTRYPOINT,在創建容器的時候會運行此命令,執行腳本,起應用服務
ENTRYPOINT ["sh","/root/xxxserver/uwsgi_run.sh"]
在對應的腳本文件中,這樣設置:
#!/bin/bash
# run itpserver with uwsgi
/usr/local/bin/uwsgi -d --ini /opt/big_factory/xxxserver/xxxapi_uwsgi.ini
# never exit,此處是為了運行完上條應用服務后,有對應的前台進程
tail -f /dev/null
本文中的腳本文件用的是 tail 命令,當然也可以用其他的命令,如ping, top, sleep等,只不過tail相對系統開銷小,而且/dev/null是個黑洞,啥都可以往里扔,也不顯示。
接下來看看效果怎樣。
在docker build新鏡像后,同樣docker-compose up -d啟動容器服務,查看容器狀態docker-compose ps,進入容器並查看進程:

事實證明,確實有效。
上述操作,解決了 docker-compose 啟動容器時,運行腳本文件來起容器內部的應用程序,且容器正常運行up的需求。
總結
如果我們通過 docker-compose 運行容器,並運行內部應用服務的話,可以按照以下設置進行操作:
-
1.編寫Dockerfile,在文件中設置
ENTRYPOINT指令,一般可以執行啟動應用的腳本文件,腳本文件最后應該有不退出的命令,如tail/top/ping等,然后通過docker build -t name:tag .創建新的鏡像 -
2.編寫docker-compose.yml/yaml文件,內部指定基於Dockerfile創建的鏡像
-
3.通過
docker-compose up -d啟動容器
---------------------------------------------------------------------------------
此處對於 CMD | command 及 ENTRYPOINT | entrypoint 在 dockerfile 和 docker-compose 並未詳細涉及,詳情請看以下博文:
docker容器之dockerfile&docker-compose CMD/entrypoint詳解
