Docker 化部署:多阶段构建与健康检查
容器化是官方推荐的云时代部署方式:一次构建、随处运行,配合编排工具可水平扩展。官方容器部署章节的示例是“静态编译产物 + 轻量 alpine 基础镜像”,单文件运行、镜像可做到 20MB 级别。本章在该官方范式上补充多阶段构建与健康检查两个工程实践。
为什么静态编译 + 轻量镜像
Go 交叉编译是语言级能力,静态编译产物不依赖服务器上的动态库。官方示例先编译再打镜像:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main main.go
然后基于 alpine 类基础镜像制作运行镜像(官方示例用 loads/alpine 系镜像,约 20MB 级)。这样镜像里只有“可执行文件 + 资源”,攻击面与体积都小。
多阶段 Dockerfile
多阶段构建把“编译环境”和“运行环境”分开:编译阶段用完整 Go 镜像,运行阶段只复制产物,最终镜像不携带编译器与源码。
# ---- 阶段一:编译 ----
FROM golang:1.22-alpine AS builder
WORKDIR /src
# 先拷依赖清单,充分利用镜像层缓存
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# 静态编译(官方文档推荐的编译参数)
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /out/main main.go
# ---- 阶段二:运行 ----
FROM alpine:3.20
WORKDIR /app
COPY --from=builder /out/main /app/main
COPY manifest /app/manifest # 配置文件/静态资源按需拷入
EXPOSE 8000
HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
CMD wget -q -O /dev/null http://127.0.0.1:8000/healthz || exit 1
CMD ["/app/main"]
应用侧配一个健康检查端点,供 Docker/编排平台探活:
package main
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
)
func main() {
s := g.Server()
s.BindHandler("/healthz", func(r *ghttp.Request) {
r.Response.Write("ok")
})
s.SetPort(8000)
s.Run()
}
构建与运行:
docker build -t gf-app .
docker run -d --name gf-app -p 8000:8000 gf-app
docker inspect --format='{{json .State.Health}}' gf-app # 查看健康状态
alpine 自带 busybox wget,健康检查无需额外安装工具;若运行镜像里没有 wget/curl,也可改用 CMD-SHELL 配合其他可用命令。
配置与资源的处理方式
- 官方文档提示:静态文件(如前端资源)与配置(如使用配置中心时)可能不进镜像,按项目形态裁剪。例如前后端分离时不需要
public目录。 - 需要进程内文件时可用
gf pack资源打包,把配置/资源编进二进制,减少外部依赖(官方有专门章节)。 - 数据库、Redis 用容器编排或外部服务,通过环境变量/配置注入地址,避免把连接串写死在镜像里。
注意点
- 多阶段构建中
go mod download单独成层可大幅加速反复构建。 - 健康检查接口应轻量:不要让它去查数据库/Redis 再返回,否则依赖抖动会误杀容器(依赖可用性由业务请求面衡量更合理)。
- 时区:alpine 基础镜像默认 UTC,与上一章时区要求冲突时,在 Dockerfile 中设置
TZ环境变量或运行时注入。 - 编排(Kubernetes/Swarm)下的优雅退出依赖
SIGTERM,务必配合上一章的优雅退出逻辑。
小结
Docker 化的推荐范式 = 多阶段构建产出静态单文件 + 轻量运行镜像 + /healthz 健康检查 + 配置外置。官方示例主打“静态编译 + 轻量镜像”,多阶段与探活是建立在其上的标准工程实践,细节以官方文档 goframe.org 为准。