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