在 Docker 中,一个镜像可以由多个分层(Layer)组成。每个分层都表示一些修改或添加到上一个分层的文件系统差异。
Golang 在构建 Docker 镜像时也支持类似的机制,通过 docker build 命令来创建一个包含多个分层的镜像。
具体实现方式是在 Dockerfile 中使用 RUN、ADD、COPY 等指令来安装软件包、下载文件等操作,并且使用 -o 选项设置编译输出目录:
FROM golang:1.16
WORKDIR /go/src/app
COPY . .
RUN go get -d -v ./...
RUN go install -v ./...
CMD ["app"]
上面的例子中,我们从 Golang 官方镜像开始构建一个新镜像,并设置工作目录为 /go/src/app。然后复制当前目录下所有文件到容器中,并执行 go get 和 go install 命令安装和编译 Go 代码。最后设置容器启动命令为 app。
在执行这个 Dockerfile 的过程中,Docker 会将每个指令生成的结果保存为一个新的分层,并将它们合并成最终的镜像。这种机制有助于减小镜像大小,避免重复数据存储。
如果你想查看某个 Docker 镜像的所有分层信息,可以使用 docker history 命令:
$ docker history my-image
IMAGE CREATED CREATED BY SIZE COMMENT
d34e5b1a58b3 5 days ago /bin/sh -c #(nop) CMD ["app"] 0B
<missing> 5 days ago /bin/sh -c go install -v ./... 4.57MB
<missing> 5 days ago /bin/sh -c go get -d -v ./... 43.9MB
<missing> 5 days ago /bin/sh -c #(nop) COPY dir:86fd420f94bef8f09... 2.61kB
<missing> 6 weeks ago /bin/sh -c #(nop) WORKDIR /go/src/app 0B
<missing> 6 weeks ago /bin/sh -c #(nop) COPY file:d75a3e0d6401fcdb7... 116B
<missing> 6 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 6 weeks ago /bin/sh -c #(nop) ADD file:e0da07f59373bac823... 811MB
上面的结果显示了该镜像中每个分层所包含的文件、大小以及生成方式。
需要注意的是,由于 Docker 镜像的设计原理,某些操作(例如 apt-get update)可能会导致多次创建分层,从而增加镜像大小。因此在编写 Dockerfile 的时候要尽量避免重复或无效的操作,以减小镜像大小。




