首页 > 解决方案 > 构建过程中的信息传递和 Docker 中间容器创建究竟是什么?

问题描述

我有一个在本地运行的简单 Dockerfile:

FROM golang:alpine
COPY . /go/src/analytics
RUN cd /go/src/analytics  
RUN go clean
RUN go build
ENV PORT 8082
EXPOSE 8082
ENTRYPOINT analytics  

本地文件夹包含以下文件Dockerfilego.modmain.go

当我跑步时,docker-compose我得到:

Building analytics
Sending build context to Docker daemon   5.12kB
Step 1/8 : FROM golang:alpine
 ---> 7762f5dece68
Step 2/8 : COPY . /go/src/analytics
 ---> 8b943980fef8
Step 3/8 : RUN cd /go/src/analytics
 ---> Running in be8cc536c7af
Removing intermediate container be8cc536c7af
 ---> 6171b59a3b5e
Step 4/8 : RUN go clean
 ---> Running in f8528c5dc577
Removing intermediate container f8528c5dc577
 ---> c370fd1b7c04
Step 5/8 : RUN go install
 ---> Running in 540a67b77147
go: go.mod file not found in current directory or any parent directory; see 'go help modules'
The command '/bin/sh -c go install' returned a non-zero code: 1
ERROR: Service 'analytics' failed to build : Build failed

我已经看过这个这个这个,但我还是不明白。

问题:

  1. 有了COPY . /go/src/analytics,我假设所有三个文件Dockerfilego.mod并被main.go复制到一个中间容器8b943980fef8。执行下一个命令时RUN,这三个文件是否被复制到下一个中​​间容器中be8cc536c7af
  2. 据我了解,容器的进程和文件系统与其他容器分开。因此,随着每个中间容器的创建,Docker 构建过程实际上是花时间将文件和任何其他上下文复制到下一个中​​间容器,还是只是记录所有容器并为它们提供一个公共命名空间?
  3. 由于我收到错误go.mod file not found in current directory,我假设文件没有被复制到容器中,或者因为clean,build和 run 命令都发生在不同的容器中,所以 run 命令无法找到任何可执行文件。实际发生了什么?
  4. 上一个问题中,我询问了额外的 Docker 存储库。这些存储库是在 Docker 构建期间创建的中间存储库吗?我知道8b943980fef8ID 实际上是 SHA256 ID 的缩写形式。
  5. 我知道我可以使用,但是当它们在两个不同的中间容器中时RUN cd /go/src/analytics && go clean && go install如何COPY . /go/src/analytics工作?RUN cd /go/src/analytics

标签: dockerdocker-compose

解决方案


不确定我能回答所有问题,但至少要指出一些观察结果。

更改文件 stsrem 的步骤

FROMCOPYADD和步骤中的每一个RUN(可能还有其他一些步骤)最终都会对映像的文件系统进行新的更新。

这是原因之一RUN cd somewhere,作为一个独立的步骤,没有任何效果,因为它不会改变文件系统中的任何内容。

文件系统的结构是向下传递到下一层的。

WORKDIR

在 Dockerfile 中指定工作目录的正确方法是使用WORKDIR指令。这将从此点向下更改工作目录,并且可以在整个文件中多次指定。

Docker 层

通常建议将多个RUN动作组合在一起的原因,特别是如果它们属于同一个逻辑组,是为了 a) 确保它们一起执行,b) 减少中间层的数量。

更正了 Dockerfile

您的 Dockerfile 的更正版本将如下所示:

FROM golang:alpine
WORKDIR /go/src/analytics  

COPY . .
RUN go clean && go build

ENV PORT 8082
EXPOSE 8082
ENTRYPOINT analytics

码头工人检查

您似乎对 docker 构建过程的内部工作原理(或不是?)感到好奇 - 您可能想尝试一些用于 docker 检查的工具,例如潜水- 这也可能有助于解决您的其他问题。

经验法则

当我开始构建 Dockerfiles 时,一条对我有帮助的经验法则是:在您构建的映像中,将每个 或 step 想象ADDCOPYRUN正在启动一个新的 shell 会话。最后,只有您生成的文件很重要,因为它们将成为后续步骤的基础。


推荐阅读