简体   繁体   English

对Dockerfile中的CMD / ENTRYPOINT感到困惑

[英]Confused about CMD/ENTRYPOINT in Dockerfile

I am unsure what to use for ENTRYPOINT vs CMD for my Dockerfile below. 我不确定要使用什么ENTRYPOINT VS CMDDockerfile以下。

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'"]

My MongoDB initialization is based on the one supplied with the standard image. 我的MongoDB初始化基于标准映像随附的初始化。 They use mongod as the CMD . 他们使用mongod作为CMD

I need a few things - start mongo, create the user then run my scripts - setup and start. 我需要一些东西-启动mongo,创建用户,然后运行我的脚本-设置并启动。

There are no errors. 没有错误。 However, after ENTRYPOINT finishes doing its' thing, the container just exits. 但是,在ENTRYPOINT完成其操作后,容器将退出。 I want it to stay running!!! 我希望它继续运行!!!

My guess that my CMD is wrong. 我猜我的CMD错误。 Please advise. 请指教。

Thank you 谢谢

After ENTRYPOINT finishes doing it's thing, the container just exits. ENTRYPOINT完成操作后,容器就退出了。

This is a universal truth: the lifetime of a container is exactly the lifetime of the ENTRYPOINT , or absent one, the CMD . 这是一个普遍的事实:容器的生存期恰好是ENTRYPOINT的生存期,或者没有CMD的生存期。

In terms of style, don't try writing very long scripts like that inline in a Dockerfile. 就样式而言,不要尝试在Dockerfile中内联编写很长的脚本。 Make it be a separate file, COPY it into the image, make sure it's executable, and just run it directly. 使它成为一个单独的文件,将其COPY到映像中,确保它是可执行文件,然后直接运行它。

The other style point is that it's very useful to get a debugging shell in a built image like 另一个样式要点是,在已构建的映像中获得调试外壳非常有用,例如

docker run --rm -it imagename bash

But, that form only overwrites the CMD . 但是,该形式只会覆盖CMD That means you should generally put the command you want to run in CMD exclusively. 这意味着通常应该只将要运行的命令放在CMD Since this will be the main container process, it must be something that stays running for as long as the container will be; 由于这将是主要的容器过程,因此它必须一直运行到容器将一直运行下去。 it can't be something like start.sh or service start that tries to launch it in the background and immediately returns. 不能像start.shservice start试图在后台启动它并立即返回的东西。 For example, 例如,

CMD ["/opt/project/myservice", "--foreground"]

What good is ENTRYPOINT , then? ENTRYPOINT什么用呢? If you have both ENTRYPOINT and CMD , the ENTRYPOINT will get run with the CMD as command-line arguments. 如果您同时拥有ENTRYPOINTCMD ,则ENTRYPOINT将与CMD作为命令行参数运行。 A very common pattern is to write a script that does some initial setup, then does exec "$@" to run the command part. 一个非常常见的模式是编写一个脚本,该脚本进行一些初始设置,然后exec "$@"以运行命令部分。 From your example, 从您的例子来看,

#!/bin/sh
./init_mongo.sh
exec "$@"

And your combined Dockerfile could look more or less like 而且您组合的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM