最佳实践
- 下载依赖项作为一个单独的步骤来利用Docker的缓存。
- 利用缓存挂载到/go/pkg/mod/来加快后续构建。
- 利用绑定挂载 (bind mounts)来引入go.sum和go.mod文件,而不是将这些文件复制到容器中。
- 这样做可以减少构建时的数据复制操作,加快构建速度,并确保容器中的文件总是与宿主机上的文件同步
- 这意味着在这个目录下的所有文件都会被缓存,即使在多次构建容器会被销毁。
- 缓存Go模块,避免在每次构建时都需要重新下载,从而加速构建过程
- 多阶段构建:首先使用一个包含 Golang 编译环境的较大镜像进行构建,然后在第二个阶段使用轻量级的 Alpine Linux 镜像运行应用。这样做可以显著减小最终镜像的体积,提高运行时效率
- 跨平台构建, 一次部署即可编译构建多个平台架构的软件包
Docker 层缓存机制原理
docker的每个指令 都是一个分层 如果有任何一层的的代码有改动, 那么往下执行的代码也会重建, 即不会保留缓存
定义Dockerfile解析器的版本
用于AST的解析器规则, 实验版本包含未经过长期验证, 但包含新的特性
稳定版本
syntax=docker/dockerfile:1
, 表示使用最新的 1.x.x和补丁版本进行更新docker/dockerfile:1.2
: 使用最新的 1.2.x 补丁版本保持更新,并在版本 1.3.0 发布后停止接收更新。docker/dockerfile:1.2.1
; 固定版本
实验版本
- docker/dockerfile:labs - 频道上的 labs 最新版本。
- docker/dockerfile:1-labs - 与 dockerfile:1 相同,并启用了实验性功能。
- docker/dockerfile:1.2-labs - 与 dockerfile:1.2 相同,并启用了实验性功能。
- docker/dockerfile:1.2.1-labs - 不可变:从不更新。与 dockerfile:1.2.1 相同,并启用了实验性功能。
打包应用
- 单个包打包:
go build -o /bin/main .
- 带版本的二进制文件:
go build -ldflags="-X main.Version=${VERSION}" -o /bin/main .
- 多个二进制文件的形式:
go build -ldflags="-X main.Version=${VERSION}" -o /bin/ ./...
环境变量:
注意事项
设置ARG变量只能在当前的层使用
例如:
# 当前层
ARG GO_IMAGE=golang:1.23.1-alpine3.20
ARG GO_PROXY=https://proxy.golang.com.cn,direct
FROM --platform=$BUILDPLATFORM ${GO_IMAGE} AS build
# 非GO_PROXY所在的层, 无 法获取`GOPROXY`环境变量
RUN go env -w GOPROXY="$GO_PROXY"
docker运行时会无法获取GOPROXY
环境变量:
#10 [build 4/7] RUN go env -w GOPROXY="$GO_PROXY"
#10 CACHED
#11 [build 5/7] RUN --mount=type=cache,target=/go/pkg/mod/ --mount=type=bind,source=go.sum,target=go.sum --mount=type=bind,source=go.mod,target=go.mod go mod download -x
#11 0.093 go: GOPROXY list is not the empty string, but contains no entries
正确的方法:
# 定义基础镜像的 Golang 版本
ARG GO_IMAGE=golang:1.23.1-alpine3.20
FROM --platform=$BUILDPLATFORM ${GO_IMAGE} AS build
WORKDIR /src
# Go的环境变量, 例如alpine镜像不内置gcc,则关闭CGO很有效
ARG GO_PROXY=https://proxy.golang.com.cn,direct
# 设置环境变量
# RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go env -w GOPROXY="$GO_PROXY"
使用
定义默认值
# 定义基础镜像的 Golang 版本
ARG GO_IMAGE=golang:1.23.1-alpine3.20
FROM --platform=$BUILDPLATFORM ${GO_IMAGE} AS build
WORKDIR /src
# Go的环境变量, 例如alpine镜像不内置gcc,则关闭CGO很有效
ARG GO_PROXY=https://proxy.golang.com.cn,direct
# 设置环境变量
# RUN go env -w GOPROXY=https://goproxy.cn,direct
RUN go env -w GOPROXY="$GO_PROXY"
传递环境变量, 替换Dockerfile的内置变量:
使用--build-arg
属性
export version=v2.0.0
export repository="lisa/backend"
docker build \
--progress=plain \
-t $repository:$version . \
--build-arg CGO_ENABLED=0 \
--build-arg GO_IMAGE=golang:1.23.1-alpine3.20 \
--build-arg version=$version \
--build-arg PORT=8080