[英]Confused about CMD/ENTRYPOINT in Dockerfile
我不确定要使用什么ENTRYPOINT
VS CMD
我Dockerfile
以下。
FROM mongo:3.4-xenial
RUN apt-get update
RUN apt-get install -y software-properties-common
RUN apt-get install zip \
unzip
RUN apt-get install -y default-jdk
RUN apt-get update -y && \
apt-get clean
RUN mkdir -p /opt/project
COPY ./project-repo/target/project-repo.zip /opt/project
WORKDIR /opt/project
RUN unzip project-repo.zip
ENTRYPOINT echo '#!/bin/bash\n\
pidfile="${TMPDIR:-/tmp}/docker-entrypoint-temp-mongod.pid" \n\
rm -f "$pidfile" \n\
# start MongoDB here \n\
mongod --logpath /var/log/mongodb.log --dbpath /data/db/ --fork --pidfilepath "$pidfile" \n\
mongo=( mongo --host 127.0.0.1 --port 27017 --quiet ) \n\
# check to see that our "mongod" actually did start up (catches "--help", "--version", MongoDB 3.2 being silly, slow prealloc, etc) \n\
# https://jira.mongodb.org/browse/SERVER-16292 \n\
tries=30 \n\
while true; do \n\
if ! { [ -s "$pidfile" ] && ps "$(< "$pidfile")" &> /dev/null; }; then \n\
# bail ASAP if "mongod" is not even running \n\
echo >&2 \n\
echo >&2 "error: mongod does not appear to have stayed running -- perhaps it had an error?" \n\
echo >&2 \n\
exit 1 \n\
fi \n\
if mongo admin --eval "quit(0)" &> /dev/null; then \n\
# success! \n\
break \n\
fi \n\
(( tries-- )) \n\
if [ "$tries" -le 0 ]; then \n\
echo >&2 \n\
echo >&2 "error: mongod does not appear to have accepted connections quickly enough -- perhaps it had an error?" \n\
echo >&2 \n\
exit 1 \n\
fi \n\
sleep 1 \n\
done \n\
mongo -- admin <<-EOF \n\
db.createUser({user:"user", pwd:"admin123", roles:[{role:"root", db:"admin"}]}); \n\
EOF' >> ./init_mongo.sh && chmod +x ./init_mongo.sh && ./init_mongo.sh && \
chmod +x /opt/project/setup.sh && /opt/project/setup.sh all && \
chmod +x /opt/project/start.sh && /opt/project/start.sh all
EXPOSE 8080
CMD ["echo 'Welcome to Demo'"]
我的MongoDB初始化基于标准映像随附的初始化。 他们使用mongod
作为CMD
。
我需要一些东西-启动mongo,创建用户,然后运行我的脚本-设置并启动。
没有错误。 但是,在ENTRYPOINT
完成其操作后,容器将退出。 我希望它继续运行!!!
我猜我的CMD
错误。 请指教。
谢谢
ENTRYPOINT
完成操作后,容器就退出了。
这是一个普遍的事实:容器的生存期恰好是ENTRYPOINT
的生存期,或者没有CMD
的生存期。
就样式而言,不要尝试在Dockerfile中内联编写很长的脚本。 使它成为一个单独的文件,将其COPY
到映像中,确保它是可执行文件,然后直接运行它。
另一个样式要点是,在已构建的映像中获得调试外壳非常有用,例如
docker run --rm -it imagename bash
但是,该形式只会覆盖CMD
。 这意味着通常应该只将要运行的命令放在CMD
。 由于这将是主要的容器过程,因此它必须一直运行到容器将一直运行下去。 不能像start.sh
或service start
试图在后台启动它并立即返回的东西。 例如,
CMD ["/opt/project/myservice", "--foreground"]
ENTRYPOINT
什么用呢? 如果您同时拥有ENTRYPOINT
和CMD
,则ENTRYPOINT
将与CMD
作为命令行参数运行。 一个非常常见的模式是编写一个脚本,该脚本进行一些初始设置,然后exec "$@"
以运行命令部分。 从您的例子来看,
#!/bin/sh
./init_mongo.sh
exec "$@"
而且您组合的Dockerfile看起来或多或少像
FROM ubuntu:18.04
# ... other setup bits ...
WORKDIR /opt/project
COPY entrypoint.sh init_mongo.sh .
RUN chmod +x entrypoint.sh init_mongo.sh
ENTRYPOINT ["/opt/project/entrypoint.sh"]
CMD ["/opt/project/myservice", "--foreground"]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.