当前位置: 首页 > 知识库问答 >
问题:

在Dockerfile中重写继承的CMD并不总是有效?

许出野
2023-03-14

在派生的DockerFile中重写CMD时,我得到了一些不一致的行为。

基本Dockerfile如下所示:

FROM myVeryBaseImage

ENV WEBAPP_CONTEXT=my-app
WORKDIR /opt/${WEBAPP_CONTEXT}

COPY app/*.jar ./${WEBAPP_CONTEXT}.jar
COPY baseconfig/* ./config/${WEBAPP_CONTEXT}/

CMD java -jar ${WEBAPP_CONTEXT}.jar --Dspring.profiles.active=docker

这个基本映像是由另一个团队提供的,很难更改它。我现在正在编写一组容器,我希望在这些容器中多次运行同一个应用程序,但配置不同。

所以我想我应该扩展映像,将更多的配置复制到映像中,并使用不同的spring配置文件运行映像:

FROM baseImage
COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/
CMD java -jar ${WEBAPP_CONTEXT}.jar -Dspring.profiles.active=${PROFILE}

并在docker-compose.yml中:

myapp-foo:
 build: ./myapp-custom
 image: myapp-custom
 environment:
  PROFILE: foo
 volumes:
  - /opt/my-app/foo:/opt/my-app

myapp-bar:
 image: myapp-custom
 environment:
  PROFILE: bar
 volumes:
  - /opt/my-app/bar:/opt/my-app

我希望有两个容器运行,分别使用application-foo.propertiesapplication-bar.properties

不过,似乎两者都使用了appplication-docker.properties,即在基本DockerFile中定义的docker配置文件。

如果我完全更改派生Dockerfile中的CMD,它就会起作用:

CMD echo "${PROFILE}"

输出分别为“foo”和“bar”。有什么可能发生的暗示吗?

我的版本是:

docker-compose version 1.8.1, build 878cff1
Docker version 1.12.3, build 6b644ec

更新:
根据@blackibiza的建议,我将派生的Dockerfile更改为

FROM baseImage
COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/
ENTRYPOINT /opt/jdk1.8.0_102/bin/java
CMD ["-jar", "${WEBAPP_CONTEXT}.jar", "-Dspring.profiles.active=foo"]
$ docker inspect --format='{{.Config.Cmd}} {{.Config.Entrypoint}}' testapp
[-jar ${WEBAPP_CONTEXT}.jar -Dspring.profiles.active=french] [/bin/sh -c /opt/jdk1.8.0_102/bin/java]
FROM baseImage
COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/
CMD ["java", "-jar", "${WEBAPP_CONTEXT}.jar", "-Dspring.profiles.active=foo"]
Error: Unable to access jarfile ${WEBAPP_CONTEXT}.jar

共有1个答案

冯野
2023-03-14

您正在寻找的是入口点的覆盖。如Docker参考中所述,

如果您想在没有shell的情况下运行,那么您必须将命令表示为JSON数组,并给出可执行文件的完整路径。此数组形式是cmd的首选格式。任何附加参数都必须单独表示为数组中的字符串:

来自ubuntu

如果您希望您的容器每次都运行相同的可执行文件,那么您应该考虑将ENTRYPOINT与cmd结合使用。请参阅入口点。

使用Composer时,您可以重写CMD参数,如下所述:

db:
  command: '-d'
  ports:
    - 5432:5432

您应该定义一个入口点,在您的情况下是:

ENTRYPOINT java
CMD ["-jar", "${WEBAPP_CONTEXT}.jar"]

在您的具体案例中,我将讨论将shell作为入口点公开,并使用脚本重写CMD,如下所示:

ENTRYPOINT /bin/sh
CMD ["./script.sh"]

在您的compose yml中:

command: './script2.sh'

更新(基于更改的问题):

docker build -t your_image:your_version --build-arg WEBAPP_CONTEXT=your_context .

若要在生成时获取该值的替换,请执行以下操作。ARG的优点是可以在您的子映像中继承

 类似资料:
  • 我发现,如果我实现自己的CMD,当我用派生映像运行容器时,我将失去基映像提供的所有功能。如果我在派生的DockerFile中放入一个CMD,我的容器就不会继续运行....如何从基映像重用相同的入口点和CMD,只需添加更多命令?我想这样做,因为我希望在每次运行新容器时都运行某些命令。(听起来对吗?) CMD[“Apache2-前景”] https://github.com/docker-librar

  • “编写一个名为clsWorker的超类和子类clsHourlyWorker和clssalariedworker。每个工人都有一个名字和一个工资率。编写计算每个员工周薪的方法computePay(int hours)。小时工按实际工作小时数获得小时工资,如果小时数最多为40小时。如果小时工工作超过40小时,则按时间半支付超出部分。受薪工人得到40小时的小时工资,无论实际小时数是多少。为继承编写一个测

  • 我正在编写一个带有对象的游戏,我想根据它的类使用不同的命令。我有一个超级类“项目”,一个子类“工具扩展项目”和“锤子扩展工具”。在项目超类(抽象)中,我有一个抽象方法“doCommand”,我在工具中覆盖了它。这很好用,我现在在工具中有一个有效的“doCommand”。但是当我想在 Hammer 中覆盖这个“doCommand”时,它只是使用工具的“doCommand”。 这来自调用方法的类的一部

  • 问题内容: 偏重于继承而不是继承 是非常流行的短语。我读了几篇文章,最后每篇文章都说 当类之间存在纯IS-A关系时,请使用继承。 本文中的一个示例: 在 Apple 和 Fruit 之间存在明显的IS-A关系,即Apple IS-A Fruit,但作者也将其显示为Apple HAS-A Fruit(组成),以显示通过继承实现时的陷阱。 我在这里变得有些困惑,声明的含义是什么 当类之间存在纯IS-A

  • 本文向大家介绍Django继承自带user表并重写的例子,包括了Django继承自带user表并重写的例子的使用技巧和注意事项,需要的朋友参考一下 1.在models里引入 2.自定义一个类继承AbstractUser 上面verbose_name是在后台显示的字段名称。 3.在settings里面配置 小知识点 以上这篇Django继承自带user表并重写的例子就是小编分享给大家的全部内容了,希

  • 问题内容: 我有两个课,和。它们看起来像这样: 此错误指向Field的: 我希望首先调用Background init ()。要将“ a,b”传递给Fields的 init (),Field会分配a和b,然后将其中包含三个0的列表分配给field。然后让Background的 init ()继续,然后调用它自己的buildField()并用包含c的列表覆盖self.field。 似乎我还没有完全理