【问题标题】:CMD doesn't run after ENTRYPOINT in DockerfileCMD 在 Dockerfile 中的 ENTRYPOINT 之后不运行
【发布时间】:2019-02-01 03:02:11
【问题描述】:

所以我有一个执行此操作的 docker 文件:

ENV ENV ${ENV}
ENV SERVICE_NAME ${SERVICE_NAME}
USER app
ENV HOME=/home/app
COPY target /home/app/target
COPY entrypoint.sh /home/app
WORKDIR /home/app
ENTRYPOINT /usr/bin/chamber exec ${ENV}_${SERVICE_NAME} -r 1 -- ./entrypoint.sh
CMD java -jar -Dspring.profiles.active=docker target/my.jar

所以 ENTRYPOINT 运行并从 AWS 参数存储中提取一些秘密,并将它们作为环境变量填充到 entrypoint.sh shell 中。 entrypoint.sh 然后对它们执行一些操作,创建一些文件等,并在其最后一行执行“exec $@”。

我当时期待 CMD 运行,但它只能看到运行“ExecStop=/usr/bin/docker stop app”的 systemd 服务文件。

systemd 服务文件这样做是为了启动容器:

ExecStart=/usr/bin/docker run --name app --memory-reservation=128m --memory=512m -e ENV=dev -e SERVICE_NAME=app 1234567890.dkr.ecr.eu-west-2.amazonaws.com/app:latest

CMD 怎么了?

【问题讨论】:

    标签: docker dockerfile


    【解决方案1】:

    https://docs.docker.com/engine/reference/builder/#understand-how-cmd-and-entrypoint-interact 中所述,如果将CMDENTRYPOINT 的“shell 形式”组合在一起,则CMD 规范将被省略:

    所以你更应该使用“执行表单”并编写如下内容:

    …
    ENTRYPOINT ["/usr/bin/chamber", "exec", "${ENV}_${SERVICE_NAME}", "-r", "1", "--", "./entrypoint.sh"]
    CMD ["java -jar", "-Dspring.profiles.active=docker", "target/my.jar"]
    

    但是这不会按原样工作,因为${ENV}${SERVICE_NAME} 不会被扩展(因为需要外壳)。

    因此,在此处应用的最简单、正确的解决方案是重构您的entrypoint.sh,或者如果您不想更改它并仍然依赖具有“执行形式”的环境变量ENTRYPOINT,你可以改写:

    …
    RUN chmod a+x entrypoint1.sh
    ENTRYPOINT ["./entrypoint1.sh"]
    CMD ["java -jar", "-Dspring.profiles.active=docker", "target/my.jar"]
    

    有一个文件

    entrypoint1.sh

    #!/bin/bash
    exec /usr/bin/chamber exec ${ENV}_${SERVICE_NAME} -r 1 -- ./entrypoint.sh "$@"
    

    【讨论】:

    • 它实际上是 exec 形式,但我真的需要那些房间为我获取的变量,否则 entrypoint.sh 不会做太多。
    • @SnazzyBootMan 我不明白你的意思:你的问题中的 ENTRYPOINT 是 shell 形式的。但是,如果您不想更改 entrypoint.sh,您可以使用额外的 entrypoint1.sh 来处理变量扩展......我将编辑我的答案来解释这一点。
    • 以前它是以 exec 形式编写的,在任务定义中与 Amazon ECS 配合得很好,可以覆盖 CMD 并用一堆变量填充环境。启动 entrypoint.sh 时会生成一个新的 shell 吗?环境变量需要自始至终维护。
    • @SnazzyBootMan 是的,确切地说:(1)为了能够使用CMD 指令,必须使用ENTRYPOINT ["program", "arg1", ...] 的形式, ENTRYPOINT program arg1 ...; (2) 如果你只写ENTRYPOINT ["./entrypoint.sh"] and entrypoint.sh 有可执行标志 (RUN chmod a+x entrypoint.sh) and entrypoint.sh 以适当的 shebang,然后会按预期生成一个shell,并扩展里面的环境变量; (3) 最后,您的入口点脚本应该包含一些代码来读取CMD 参数(参见我的回答中的"$@")。
    • 很好的答案,我今天正在尝试这个并且遇到了一些问题。在阅读您的最后一条评论时,我现在明白了为什么我使用 Alpine(我现在才刚刚提到)作为容器图像,因此复制和粘贴您的答案不会起作用,因为没有使用“适当的 shebang”。将 #!/bin/bash 替换为 #!/bin/ash 是可行的,因为我只是提到了你不知道的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2020-01-13
    • 1970-01-01
    • 2014-02-28
    • 1970-01-01
    相关资源
    最近更新 更多