最简可行方案是多阶段构建:第一阶段用 golang:1.22-alpine 编译静态二进制,CGO_ENABLED=0 且 GOOS=linux;第二阶段用 alpine:latest 运行,仅复制二进制和 ca-certificates。

用 docker build 打包 Go 二进制最简可行方案
Go 编译出的静态二进制文件天然适合 Docker 多阶段构建,核心是避免把 go 工具链和源码塞进最终镜像。别用 FROM golang:alpine 直接运行,那会带上几百 MB 的编译环境。
推荐写法:
FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o /usr/local/bin/myapp . FROM alpine:latest RUN apk --no-cache add ca-certificates COPY --from=builder /usr/local/bin/myapp /usr/local/bin/myapp CMD ["/usr/local/bin/myapp"]
-
CGO_ENABLED=0确保不依赖系统 libc,否则 Alpine 镜像可能缺动态库 -
GOOS=linux是必须的,本地 macOS/Windows 构建时容易漏掉 - 最终镜像通常 golang:alpine 运行源码小 30 倍以上
Dockerfile 中暴露端口与健康检查怎么写才生效
仅写 EXPOSE 8080 不会让容器自动监听或转发流量,它只是文档式声明。真正起作用的是你的 Go 程序绑定地址 + 容器运行时的 -p 映射。
健康检查建议用 HTTP 探针(假设你用 net/http):
立即学习“go语言免费学习笔记(深入)”;
mallcloud商城基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba并采用前后端分离vue的企业级微服务敏捷开发系统架构。并引入组件化的思想实现高内聚低耦合,项目代码简洁注释丰富上手容易,适合学习和企业中使用。真正实现了基于RBAC、jwt和oauth2的无状态统一权限认证的解决方案,面向互联网设计同时适合B端和C端用户,支持CI/CD多环境部署,并提
HEALTHCHECK --interval=10s --timeout=3s --start-period=30s --retries=3 \ CMD wget --quiet --tries=1 --spider http://localhost:8080/health || exit 1
- Go 服务启动后需监听
0.0.0.0:8080,不是127.0.0.1:8080,否则容器内健康检查失败 -
--start-period=30s给 Go 应用留够初始化时间,比如加载配置、连 DB - 别用
curl,Alpine 默认没装;wget更轻量,或改用nc -z localhost 8080
微服务间调用:Docker 网络模式选 bridge 还是 host
本地开发用 docker-compose 默认的 bridge 网络最稳妥。所有服务在同一个自定义 bridge 网络里,可以直接用服务名当 DNS 名通信。
例如 user-service 调用 auth-service:
resp, err := http.Get("http://auth-service:8080/token")
- 不要用
host模式:端口冲突、无法隔离、Mac/Windows 上行为不一致 - 不要硬编码
localhost:在容器里它指向自己,不是宿主机或其他服务 - 确保
docker-compose.yml中定义了同一networks,且各服务都加入该网络
环境变量与配置注入:为什么 os.Getenv 在容器里读不到
常见错误是只在 docker run 命令里传 -e ENV=prod,但忘了在 docker-compose.yml 或 CI/CD 流水线中同步配置。
Go 侧安全做法:
env := os.Getenv("ENV")
if env == "" {
log.Fatal("missing required ENV environment variable")
}
- 别依赖
.env文件自动加载 —— Docker 不读它,docker-compose默认读但需显式声明env_file: - 敏感配置(如数据库密码)优先用
docker secret(Swarm)或挂载tmpfs文件,而非环境变量 - Go 的
flag包在容器里基本不用,命令行参数难维护,环境变量 + 配置文件更清晰









