Docker 多阶段构建实战:把 Go 服务镜像从 900MB 压到 15MB
【摘要】 背景在华为云 Flexus 云服务器上部署小服务时,镜像体积直接影响拉取速度和磁盘占用。很多人直接用 golang 官方镜像构建并运行,结果镜像动辄 800~900MB。Docker 的多阶段构建(multi-stage build)可以把“编译环境”和“运行环境”分开,只把最终产物拷进一个极小的基础镜像里。下面用一个简单的 Go HTTP 服务演示完整过程。 第一步:准备示例代码// m...
背景
在华为云 Flexus 云服务器上部署小服务时,镜像体积直接影响拉取速度和磁盘占用。很多人直接用 golang 官方镜像构建并运行,结果镜像动辄 800~900MB。Docker 的多阶段构建(multi-stage build)可以把“编译环境”和“运行环境”分开,只把最终产物拷进一个极小的基础镜像里。下面用一个简单的 Go HTTP 服务演示完整过程。
第一步:准备示例代码
// main.go
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello from multi-stage build")
})
http.ListenAndServe(":8080", nil)
}
再执行 go mod init demo 生成 go.mod。
第二步:单阶段写法(对照组)
FROM golang:1.22
WORKDIR /app
COPY . .
RUN go build -o server .
CMD ["./server"]
构建后用 docker images 查看,体积约 850MB 以上,因为整个 Go 工具链都被打包进去了。
第三步:改成多阶段构建
# 阶段一:编译
FROM golang:1.22 AS builder
WORKDIR /src
COPY go.mod ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /out/server .
# 阶段二:运行
FROM alpine:3.20
RUN adduser -D -u 10001 app
COPY --from=builder /out/server /usr/local/bin/server
USER app
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/server"]
要点说明:
CGO_ENABLED=0生成静态二进制,不依赖 glibc,才能放进 alpine 甚至 scratch。-ldflags="-s -w"去掉符号表和调试信息,二进制能再小三成左右。- 先单独 COPY go.mod 再下载依赖,可以利用构建缓存,代码改动时不用重复下载依赖。
- 运行阶段用非 root 用户,降低容器被攻破后的风险。
第四步:构建与验证
docker build -t demo:multi .
docker images demo
docker run -d -p 8080:8080 --name demo demo:multi
curl http://127.0.0.1:8080
此时镜像只有十几 MB。如果把运行阶段换成 FROM scratch,还能进一步压到 7MB 左右,但要注意 scratch 里没有 shell 和 CA 证书,需要 HTTPS 请求时要额外拷贝 /etc/ssl/certs。
第五步:推送到华为云 SWR
构建好的镜像可以推到华为云容器镜像服务 SWR,方便多台服务器拉取:
docker tag demo:multi swr.cn-north-4.myhuaweicloud.com/<组织名>/demo:v1
docker push swr.cn-north-4.myhuaweicloud.com/<组织名>/demo:v1
登录指令可在 SWR 控制台“总览—登录指令”里获取。镜像变小之后,推送和拉取都明显更快。
小结
- 多阶段构建把编译依赖留在第一阶段,最终镜像只保留运行所需文件。
- 静态编译 + 精简基础镜像是压缩体积的关键。
- 合理安排 COPY 顺序能充分利用缓存,加快日常构建。
这套写法同样适用于 Java(Maven 构建 + JRE 运行)、前端(Node 构建 + Nginx 托管)等场景,值得在自己的项目里试一试。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)