Docker部署Golang项目
为什么用Docker部署Golang项目
Golang编译出的二进制文件本身不依赖运行时环境,
但部署时仍可能遇到系统库版本、
目录结构、
端口冲突等问题。用Docker封装后,
项目与依赖一起打包成镜像,
在任何装了Docker的服务器上都能一键运行,
彻底告别“我本地能跑”的尴尬。
准备工作
- 一台安装好Docker的服务器(CentOS/Ubuntu均可),执行
sudo docker --version可看到版本号。 - 一个已编译好的Golang项目(含
go.mod、main.go等源文件),或直接使用二进制文件。 - 确保服务器防火墙开放了项目要用的端口(比如 8080)。
第一步:编写高效的Dockerfile
在项目根目录创建 Dockerfile(无后缀),内容示例如下:
# 使用官方Golang镜像作为构建环境
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o myapp .
# 使用空镜像(scratch)作为运行环境,减小体积
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]
关键点:
- 多阶段构建:第一阶段编译,第二阶段只复制二进制,镜像体积可从数百MB降到十几MB。
CGO_ENABLED=0:禁用CGo,生成静态二进制,避免依赖系统库。- 添加
ca-certificates:解决HTTPS请求报证书错误。 - 设置时区:
tzdata包确保日志时间正确。
第二步:构建镜像并运行容器
在项目目录执行以下命令:
# 构建镜像,标签为 my-golang-app:v1
docker build -t my-golang-app:v1 .
# 运行容器,将宿主机的 8080 端口映射到容器的 8080
docker run -d --name myapp -p 8080:8080 my-golang-app:v1
运行后执行 docker ps 查看容器状态。
如果状态为 Up,说明启动成功。
第三步:高频问题与避坑指南
Q1:构建时依赖下载很慢?
用国内代理:在 go mod download 前添加 ENV GOPROXY=https://goproxy.cn。
Q2:容器启动后立刻退出?
执行 docker logs myapp 查看日志。
常见原因:
- 项目绑定了
0.0.0.0而不是localhost(Docker容器内部必须监听0.0.0.0)。 - 端口冲突:宿主机的8080已被占用,改用别的端口,如
-p 8081:8080。
Q3:镜像体积太大?
检查是否用了完整镜像(如 golang:latest)作为运行阶段,应该用 alpine 或 scratch。
另外清理 go build 的缓存:在builder阶段添加 RUN rm -rf /go/pkg/mod。
Q4:如何更新代码?
修改代码后重新执行 docker build,然后停止旧容器并启动新容器:
docker stop myapp
docker rm myapp
docker run -d --name myapp -p 8080:8080 my-golang-app:v2
验证部署结果
访问 http://服务器公网IP:8080/你的接口路径,如果项目是Web服务,浏览器应正常返回页面或JSON。
也可以使用 curl 验证:
curl http://localhost:8080/health
若返回 200 或业务正常内容,则Docker部署Golang项目成功。
总结
掌握Docker部署Golang项目的核心就是写好Dockerfile、用好多阶段构建、注意端口和监听地址。
按照本文步骤走一遍,你就能把Golang项目稳定跑在容器中,后续结合Docker Compose还能实现一键启动多个服务。
如果在实操中遇到报错,优先用 docker logs 定位问题,大多都能在本文避坑部分找到答案。