如果使用官方的golang镜像来制作GO程序镜像(如下的Dockerfile文件所示),无论程序简单还是复杂,镜像大小都在500M以上,非常浪费存储容量以及不容易传输。
FROM golang:latest
# 设置工作目录
WORKDIR /app
# 复制go.mod和go.sum以提高构建效率
COPY go.mod go.sum ./
# 下载依赖
RUN go mod download
# 将当前目录的所有文件复制到工作目录中
COPY . .
# 构建Go应用
RUN go build -o main .
# 暴露应用程序监听的端口(如果有的话)
EXPOSE 8080
# 执行应用程序
CMD ["./main"]
因此,可以采用采用多阶段构建的Dockerfile,第一阶段使用golang镜像中编译可执行文件/app/main,第二阶段将该可执行文件复制到更精简的镜像alpine中,最终镜像大小通常不到100M。Dockerfile内容如下:
# 阶段一:构建阶段
FROM golang:latest AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# 构建静态链接的可执行文件
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .
# 阶段二:运行阶段
FROM alpine:latest
WORKDIR /app
# 从构建阶段复制可执行文件
COPY --from=builder /app/main .
# 暴露应用程序监听的端口(如果有的话)
EXPOSE 8080
# 执行应用程序
CMD ["./main"]
在某些极为精简的需求之下,甚至可以采用scratch空镜像,不过值得注意的是,scratch镜像只有根目录,且不支持sh或bash类命令,因此无法进入容器内交互。由于只有根目录的原因,需要对上文的Dockerfile文件进行更改,要么主动构造/APP文件里,要么将WORKDIR设置为/根目录。
使用一个简单的hello world程序进行测试,可以看到golang制作的镜像为816MB,alpine制作的镜像为9.19MB,scratch制作的镜像为1.85MB。
在适合的场景下选择恰当的基础镜像,可以更好地提升工作效率。