英文:
How to run both CMD and ENTRYPOINT scripts if they are in different images?
问题
我正在使用Docker多阶段构建,并尝试为我的Docker化Go应用程序添加实时重新加载功能。我在第二个镜像中有一个具有自己配置的entrypoint.sh。
现在的问题是,第一个镜像中的命令CMD ["air", "-c", ".air.toml"]
被第二个镜像中的ENTRYPOINT ["/entrypoint.sh"]
脚本覆盖,所以只有ENTRYPOINT
被启动,CMD
不会运行。
我不能将它们合并为一个命令,像这样
ENTRYPOINT ["/entrypoint.sh", "air", "-c", ".air.toml"]
因为第二个镜像没有安装Golang语言和相应的库。
有没有办法让CMD
和ENTRYPOINT
并行运行?谢谢。
Dockerfile
FROM golang:1.17.2
COPY . /go/src/sample
WORKDIR /go/src/sample
RUN go install github.com/go-delve/delve/cmd/dlv@latest
RUN go install github.com/cosmtrek/air@latest
CMD ["air", "-c", ".air.toml"]
FROM eclipse-temurin:17-focal
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
docker-compose.yml
version: '3'
services:
go:
build:
context: ./backend
dockerfile: Dockerfile
volumes:
- ./backend:/go/src/backend
working_dir: /go/src/backend
ports:
- 8080:8080
英文:
I'm using docker multistage build and am trying to add a live reload feature to my dockerized go application. I have an entrypoint.sh with its own configurations in the second image.
Now, the problem is that the command CMD ["air", "-c", ".air.toml"]
from the first image gets overwritten by the ENTRYPOINT ["/entrypoint.sh"]
scripts from the second image, so it is only the ENTRYPOINT
that is started and CMD
doesn't run.
I can't combine them into the only command like so
ENTRYPOINT ["/entrypoint.sh", "air", "-c", ".air.toml"]
because the second Image doesn't have Golang language installed with the respective libraries.
Is it possible somehow to run CMD
and ENTRYPOINT
side by side? Thank you.
Dockerfile
FROM golang:1.17.2
COPY . /go/src/sample
WORKDIR /go/src/sample
RUN go install github.com/go-delve/delve/cmd/dlv@latest
RUN go install github.com/cosmtrek/air@latest
CMD ["air", "-c", ".air.toml"]
FROM eclipse-temurin:17-focal
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
docker-compose.yml
version: '3'
services:
go:
build:
context: ./backend
dockerfile: Dockerfile
volumes:
- ./backend:/go/src/backend
working_dir: /go/src/backend
ports:
- 8080:8080
答案1
得分: 1
读取传递给入口点的参数,即CMD。
例如,下面是您的入口点脚本。您可以访问这些参数并对其进行操作,例如执行它们。
#!/bin/bash
# 在入口点中执行一些操作
# 执行原始命令
# 替换当前进程ID
# 以使命令以pid 1运行
exec "$@"
在您的Docker镜像中,确保有所需的命令,例如:
ENTRYPOINT ["/entrypoint.sh"]
CMD ["echo", "command"]
除了这个技术方面,您似乎暗示您想要在没有go可用的情况下运行依赖于go的CMD。这是不可能的。您需要确保您尝试执行的内容及其依赖项可用。
您可以从第一阶段复制air二进制文件。类似于以下内容:
COPY --from=0 /go/bin/air /usr/local/bin/air
可能,您希望使用CGO_ENABLED=0
编译air
。
然而,我认为您需要在镜像中安装go编译器才能进行任何热重载,因为您的应用程序需要在代码更改时重新编译。所以也许您不应该在这里使用多阶段构建。
话虽如此,但在容器中进行热重载似乎有点违反常规。容器通常用于分发您的构件。
英文:
Read the arguments passed to the entrypoint which is the CMD.
For example, below is your entrypoint script. You can access the args and do something with them, i.e. execute them.
#!/bin/bash
# dome something in your entrypoint
# execute the original command
# substituting the current process id
# so that command is run with pid 1
exec "$@"
In your docker image, make sure you have the desired command, i.e.
ENTRYPOINT ["/entryppoint.sh"]
CMD ["echo", "command"]
Apart from this technical aspect, you seem to imply that you want to run the CMD that relies on go being available without go being available. That is not possible. You need to ensure the thing you are trying to execute and its dependencies are available.
You can probably copy the air binary from the first stage. Something like this.
COPY --from=0 /go/bin/air /usr/local/bin/air
Potentially, you want to compile air
this with CGO_ENABLED=0
.
However, I would assume that you need the go compiler to be present in your image for any hot reload to work, since your app needs to be recompiled on code change. So perhaps you should not even use multi staging here.
That, said. Doing hot reload in a container seems a bit like an anti pattern. Containers are usually a mean to distribute your artifacts.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论