docker - 构建过程中的信息传递和 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
本地文件夹包含以下文件Dockerfile
:go.mod
和main.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
问题:
- 有了
COPY . /go/src/analytics
,我假设所有三个文件Dockerfile
,go.mod
并被main.go
复制到一个中间容器8b943980fef8
。执行下一个命令时RUN
,这三个文件是否被复制到下一个中间容器中be8cc536c7af
? - 据我了解,容器的进程和文件系统与其他容器分开。因此,随着每个中间容器的创建,Docker 构建过程实际上是花时间将文件和任何其他上下文复制到下一个中间容器,还是只是记录所有容器并为它们提供一个公共命名空间?
- 由于我收到错误
go.mod file not found in current directory
,我假设文件没有被复制到容器中,或者因为clean
,build
和 run 命令都发生在不同的容器中,所以 run 命令无法找到任何可执行文件。实际发生了什么? - 在上一个问题中,我询问了额外的 Docker 存储库。这些存储库是在 Docker 构建期间创建的中间存储库吗?我知道
8b943980fef8
ID 实际上是 SHA256 ID 的缩写形式。 - 我知道我可以使用,但是当它们在两个不同的中间容器中时
RUN cd /go/src/analytics && go clean && go install
如何COPY . /go/src/analytics
工作?RUN cd /go/src/analytics
解决方案
不确定我能回答所有问题,但至少要指出一些观察结果。
更改文件 stsrem 的步骤
FROM
、COPY
、ADD
和步骤中的每一个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 想象ADD
成COPY
您RUN
正在启动一个新的 shell 会话。最后,只有您生成的文件很重要,因为它们将成为后续步骤的基础。
推荐阅读
- java - 为什么他们为答案显示 1 次但已经创建了 2 个线程
- visual-studio - 无法禁用对撞机
- sitecore - 在 Sitecore Glass 映射器中获取过滤的项目
- node.js - DynamoDB sql 查询扫描以获取日期时间范围计数
- macos - dnsmasq - Apple Silicon M1 上的服务状态问题
- excel - 基于多个单元格值隐藏/取消隐藏行
- javascript - typeError:无法读取未定义的属性“PROVIDER_ID”我正在使用最新的 SDK
- r - 删除重复行并更改 R 中数据框中的值
- dpdk - 如何禁用 RSS 但仍在 DPDK 中使用多个 RX 队列?
- flutter - Flutter 中的 ReactJS 子代等价物