Docker 化:多阶段构建、健康检查、docker compose 简单编排
容器化让「环境一致」成为默认:把编译与运行拆成两个阶段,镜像里只留运行所需的最小文件。本章以多阶段 Dockerfile + docker compose 编排为例,命令语法以 Docker 官方文档为准。
1. 多阶段 Dockerfile
第一阶段用带 Go 工具链的镜像编译,第二阶段用精简镜像只放产物:
# ---- 构建阶段 ----
FROM golang:1.22-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/app ./cmd/server
# ---- 运行阶段 ----
FROM alpine:3.20
RUN adduser -D -H appuser
COPY --from=build /out/app /usr/local/bin/app
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -qO- http://127.0.0.1:8080/healthz || exit 1
ENTRYPOINT ["/usr/local/bin/app"]
- 先
COPY go.mod go.sum再go mod download:利用层缓存,依赖不变就不重下; - 以非 root 运行(
USER appuser)是基本安全要求; HEALTHCHECK让编排系统能感知容器存活。
2. 应用内健康检查接口
Dockerfile 探活的地址必须真实存在:
r.GET("/healthz", func(c *gin.Context) {
if err := pingDB(c.Request.Context()); err != nil {
c.JSON(http.StatusServiceUnavailable, gin.H{"status": "down"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "up"})
})
依赖的 MySQL/Redis 挂了就返回 503,编排层才能正确调度。
3. docker compose 简单编排
把 app 与依赖(MySQL、Redis)编在一起:
services:
app:
build: .
ports:
- "8080:8080"
environment:
DB_DSN: "root:secret@tcp(mysql:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"
REDIS_ADDR: "redis:6379"
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: demo
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"]
interval: 10s
timeout: 3s
retries: 5
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:7-alpine
volumes:
mysql_data:
容器间用服务名通信(mysql、redis),应用配置里的地址要写服务名而不是 localhost。启动:docker compose up -d --build。
4. 环境与密钥
- 配置全部走环境变量,compose 里用
env_file或.env管理; - 密钥别写进镜像:用 secret 管理或外部注入,镜像里只留占位默认值。
注意点
- 多阶段里
CGO_ENABLED=0与目标架构要匹配;ARM 机器换GOARCH=arm64或做多架构构建。 - 数据库密码等敏感信息不要硬编码进 compose 文件并提交代码库。
- 本地调试常用
docker compose up覆盖配置;生产可考虑更完善的编排平台。
小结
多阶段构建出「小且安全」的镜像,healthcheck 让依赖状态可感知,compose 把多服务串起来。容器化之后,下一章回到协议层,讲 WebSocket 实时通信怎么接。