【问题标题】:Building clean Go application in Docker在 Docker 中构建干净的 Go 应用程序
【发布时间】:2019-05-05 10:34:15
【问题描述】:

我正在尝试将 Go Web 服务器创建为小型 Docker 映像。理想情况下,干净的镜像只包含 Go 应用程序本身(可能支持 Web 组件,但不包含 Go 构建环境)。

这是我的Dockerfile

# golang:latest as build-env
FROM golang:latest AS build-env

RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN cd /app && GO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .
# go build -o myapp

FROM scratch
COPY --from=build-env /app/myapp /app/images /

EXPOSE 8080
ENTRYPOINT /myapp

它使用 Docker Builder Pattern 和临时镜像,这是一个特殊的空的 docker 镜像。

它可以构建,但是当我运行它时,我得到:

docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused "exec: \"/bin/sh\": stat /bin/sh: no such file or directory": unknown.

更新:

所以ENTRYPOINT需要改成exec形式:

ENTRYPOINT ["/myapp"]

完成后,我收到了一个新错误:

standard_init_linux.go:207: exec user process caused "no such file or directory"

使用占用空间小的 Linux 映像作为基础(即 Alpine Linux)而不是从头开始也无济于事:

$ docker run -it -p 8080:8080 go-web-docker-small            
standard_init_linux.go:207: exec user process caused "no such file or directory"

$ docker run -it -p 8080:8080 go-web-docker-small /bin/sh -i 
standard_init_linux.go:207: exec user process caused "no such file or directory"

如何解决?谢谢!

【问题讨论】:

  • @A.R,我运行 docker 没有问题。问题是获得干净的图像只包含 Go 应用程序本身,而没有 Go 构建环境。有了它,我运行docker就没有问题了,它的最后一个命令是CMD ["go", "run", "main.go"]

标签: docker go build


【解决方案1】:

你的 Dockerfile 的最后一行是

ENTRYPOINT /myapp

ENTRYPOINT(以及 CMD 和 RUN)指令有两种形式。 "exec form" 看起来像一个 JSON 列表,并提供了一个未解释的参数列表以作为主容器进程运行。 "shell form" 看起来不像 JSON 列表,而是隐式包装在 /bin/sh -c '...' 中。

您的 ENTRYPOINT 使用 shell 形式,而 FROM scratch 图像没有 shell,从而产生您得到的错误。您可以将其更改为执行表单

ENTRYPOINT ["/myapp"]

【讨论】:

  • 另外值得一提的是,制作基础镜像 FROM scratch 也会削弱原版 Go 代码的一些功能(至少开箱即用),例如解析 SSL 或其他依赖于底层操作系统的功能(就像没有 /bin/sh 一样)。这就是为什么我们通常使用占用空间小的 Linux 映像作为基础(即 Alpine Linux)而不是从头开始。
  • 感谢 David 解决了我的第一个问题,感谢 @GustavoKawamoto 回答了我下一个我没有问过的问题——因为一旦我通过了第一个问题,我总是得到“standard_init_linux.go:207: exec user process caused "no such file or directory"”无论如何都会出错。我一直在尝试各种方法,但仍然不知道错误来自哪里,直到我在这里查看(即将再次寻求帮助)。我相信关键是缺少底层操作系统。在这种情况下,Gustavo,请给出正式的答案,因为“干净的图像只包含 Go 应用程序本身” 是错误的目标。
  • 嗯...“干净的图像只包含 Go 应用程序本身”是错误的目标,等等,my code 还是有问题。 OP 已更新。
【解决方案2】:

在构建您提供的 Dockerfile 时,我收到以下错误:

复制失败:stat /var/lib/docker/overlay2/cc1f8144192760ce7bf9cda7a7dfd0af16065901594c38609c813ea103cfd8d7/merged/app/images:没有这样的文件或目录

修复了复制命令和其他一些命令,并且正在 Dockerfile 中构建映像

# golang:latest as build-env
FROM golang:latest AS build-env

RUN mkdir /app
ADD . /app/
WORKDIR /app
RUN cd /app && GO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .
# go build -o myapp

FROM scratch
COPY --from=build-env /app/myapp .

EXPOSE 8080
ENTRYPOINT ["./myapp"]

【讨论】:

  • RE:“并且图像正在构建”。我构建它没有问题(创建一个images 文件夹,你也应该构建它)当我运行它时,我解决了问题。你能运行它吗?
  • 是的。我能跑。但是,我想知道当 /app/images 目录本身不存在时,构建命令如何为您工作。如果它正在为您构建,只需将 Dockerfile 中的 ENTRYPOINT /myapp 替换为 ENTRYPOINT [./myapp] 并尝试一次。
  • 感谢 Mayank,修复后 my code 仍然有问题 - 我总是收到“standard_init_linux.go:207: exec user process caused "no such file or directory"”错误 否有什么关系。我一直在尝试各种方法,但仍然不知道错误来自哪里,请您将您的代码发布在某个地方以便我可以尝试一下吗?
  • 我只是在使用“hello world”程序@xpt
  • 好的,我会接受你的答案并单独提出后续问题。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-07
  • 2016-06-06
  • 2021-04-25
  • 2015-11-19
  • 2018-11-15
  • 1970-01-01
相关资源
最近更新 更多