我在派生的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
此基本图片由其他团队提供,很难更改。我现在正在编写一堆容器,我想多次运行同一个应用程序,但配置不同。
所以我想我会扩展图像,将更多配置复制到其中并使用不同的弹簧配置文件运行它:
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
我原本希望有2个容器在运行,分别使用application-foo.properties
和application-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-compose的东西,只是为了看看派生图像的样子。我从java获取错误消息,试图运行容器。检查图像给出以下内容:
$ 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]
所以它仍然试图执行/bin/sh
而不是java。这看起来不像我在文档中所期望的那样。
UPDATE2: 使用CMD的JSON数组语法会触发另一个问题:
FROM baseImage
COPY config/application-*.properties ./config/${WEBAPP_CONTEXT}/
CMD ["java", "-jar", "${WEBAPP_CONTEXT}.jar", "-Dspring.profiles.active=foo"]
不会扩展${WEBAPP_CONTEXT}
的使用,从而导致错误
Error: Unable to access jarfile ${WEBAPP_CONTEXT}.jar
答案 0 :(得分:3)
您正在寻找的是覆盖入口点。 如上所述in the Docker reference,
如果你想在没有外壳的情况下运行你,那么你必须 将命令表示为JSON数组并提供完整路径 可执行文件。此数组形式是CMD的首选格式。任何 其他参数必须单独表示为字符串 阵列:
FROM ubuntu
CMD [“/ usr / bin / wc”,“ - help”]
如果您希望容器每次都运行相同的可执行文件 时间,那么你应该考虑使用ENTRYPOINT CMD。参见ENTRYPOINT。
使用Composer时,您可以覆盖CMD参数,例如explained here:
db:
command: '-d'
ports:
- 5432:5432
你应该定义一个ENTRYPOINT,在你的情况下:
ENTRYPOINT java
CMD ["-jar", "${WEBAPP_CONTEXT}.jar"]
在您的具体情况下,我将争论将shell作为入口点公开并使用脚本覆盖CMD,如:
ENTRYPOINT /bin/sh
CMD ["./script.sh"]
并在你的作品YML中:
command: './script2.sh'
更新(基于已更改的问题):
缺少的是变量的定义。在这种情况下,我建议使用 ARG 而不是 ENV 来构建传入永久值的容器:
docker build -t your_image:your_version --build-arg WEBAPP_CONTEXT=your_context .
在构建时获取值的替换。 ARG具有在子图像中继承的优势
答案 1 :(得分:3)
不要只是复制&粘贴错误的Java命令。如果-Dspring.profile.active
参数位于.jar
文件之后,则无法识别CMD java -jar -Dspring.profiles.active=${PROFILE} ${WEBAPP_CONTEXT}.jar
参数。
将CMD行修复为
{{1}}
一切都很好。
另请参阅“Setting active profile and config location from command line in spring boot”