【问题标题】:Issue with Docker multi-stage buildsDocker 多阶段构建的问题
【发布时间】:2019-09-27 04:30:17
【问题描述】:

我有一个多阶段构建的问题,其中在第一阶段构建的二进制文件被正确复制到第二阶段,但是当您尝试运行它时,找不到可执行文件。

dockerfile 是:

FROM golang as goimage
ENV SRC=/go/src/
RUN mkdir -p /go/src/
WORKDIR /go/src/go_docker
RUN git clone https://github.com/bryonbaker/simple-microservice.git /go/src/go_docker/ \
&& CGO_ENABLED=0 GOOS=linux GOARCH=amd64
RUN go get github.com/gorilla/mux
RUN go build -o bin/go_docker

FROM alpine:latest AS microservice
RUN apk --no-cache add bash
ENV WORK_DIR=/docker/bin
WORKDIR $WORK_DIR
COPY --from=goimage /go/src/go_docker/bin/ ./

# Put a container-image version identifier in the root directory.
ARG VERSION=1.0
RUN echo $VERSION > image_version

EXPOSE 10000
#CMD ["go_docker"]

结果是:

$ docker run -ti -p 80:10000 go-docker:latest
/docker/bin #ls

go_docker 镜像版本
/docker/bin # ./go_docker /bin/sh: ./go_docker: 未找到
/docker/bin #

如果我从构建的中间 goimage 容器运行二进制文件,那么它运行良好。文件大小匹配...

注意:在这个 dockerfile 中,我已经注释掉了 CMD 并正在通过 shell 进行测试。如果您取消注释 CMD,您会遇到同样的问题:

docker run go-docker:latest docker:来自守护进程的错误响应:OCI 运行时创建失败:container_linux.go:344:启动容器 进程导致“exec:\”go_docker\”:在中找不到可执行文件 $PATH":未知。 ERRO[0001] 等待容器时出错:上下文已取消

git repo 中的测试代码我已经公开了,如果你想看的话。

提前致谢

【问题讨论】:

  • 介意包括您用于构建此映像的命令吗?
  • 我可以建议一个更具体的标题吗?例如“多阶段 dockerfile 构建中缺少 go 程序”

标签: docker dockerfile


【解决方案1】:

如果二进制文件的共享库不可用,您将在 Linux 上普遍遇到此错误。 (在您的调试 shell 中,尝试运行 ldd /docker/bin/go_docker。)

您可能并不期待动态链接的二进制文件,但您会得到一个,因为 shell 和环境变量不会在 RUN 命令之间传递。如果您在 RUN 步骤的末尾设置 CGO_ENABLED=0,那么当实际的 go build 在两步之后运行时,该值会丢失。

(我还要稍微清理一下 Dockerfile:容器内的路径之类的东西不需要是变量,使用系统路径完全可以。)

这给我们留下了:

FROM golang as goimage

# Use standard $GOPATH layout?
# WORKDIR /go/src/github.com/byronbaker/simple-microservice
# COPY . .
# RUN go get .
# RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install .

# !!! Docker layer caching will not repeat this step if the repo changes
# !!! You won't be able to build a test copy of your uncommitted code
RUN git clone https://github.com/bryonbaker/simple-microservice.git /go/src/go_docker
RUN go get github.com/gorilla/mux

# vvv Put magic environment variables in this line
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go install go_docker
# ^^^

# Runtime image
FROM alpine:latest
COPY --from=goimage /go/bin/go_docker /bin/go_docker
ARG VERSION=1.0
RUN echo $VERSION > /image_version
EXPOSE 10000
CMD ["go_docker"]

【讨论】:

  • 不错的一个!我完全忘记了“安装”。你能解释一下为什么设置环境变量以后会丢失吗?我以为这个问题只发生在 FROM 之后。
  • 每个RUN 命令在新容器的新外壳中运行。你可以玩RUN export ... 之类的东西,看看它没有效果。 ENV 将跨层持续存在并显示在 RUN 命令的环境中(并且会在您启动 FROM 新图像时重置)。
猜你喜欢
  • 2020-06-05
  • 2020-07-13
  • 2022-11-25
  • 1970-01-01
  • 1970-01-01
  • 2020-04-16
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
相关资源
最近更新 更多