說下我的需求,就是在使用 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詳解