前言

之前使用dockerfile构建镜像时,都是使用单个dockerfile构建,把构建好的二进制或jar包导出重写打包为镜像,这样比较麻烦无法自动化, 从其他地方了解到可以使用多阶段构建,跟GitHub的Action类似,方便快捷。

1.使用

在Dockerfile的多阶段构建中,最终生成的镜像是以最后一个阶段的镜像为准的

每个阶段都是一个FROM,以FROM为标识多个阶段

# 第一阶段:编译
# 必须用AS定义一个自定义别名 在其他阶段要使用
FROM golang:1.18 AS builder

# 设置工作目录(创建并cd过去)
WORKDIR /app

# 从宿主机复制main.go到容器当前目录(/app/main.go)
COPY main.go .

# 执行编译命令
RUN go build -o myapp /app/main.go

# 第二阶段:生成最终镜像
FROM alpine:latest

# 设置工作目录(创建并cd过去)
WORKDIR /root/

# 从第一阶段复制文件到第二阶段中
# --from 指定把builder阶段中的/app/myapp文件复制到当前镜像当前目录中(/root/myapp)
COPY --from=builder /app/myapp .

# 启动命令
CMD ["./myapp"]

2.构建go镜像

1.简单的go单文件

package main

import (
	"fmt"
)

func main() {
	fmt.Println("我是多阶段构建出来的镜像")
}

2.dockerfile

# 第一阶段:编译
# 必须用AS定义一个自定义别名 在其他阶段要使用
FROM golang:1.20 AS builder

# 设置工作目录(创建并cd过去)
WORKDIR /apps

# 从宿主机复制main.go到容器当前目录(/apps/main.go)
COPY main.go .

# 设置 Go 环境变量 切换模块源为中国Go模块代理服务器
RUN go env -w GOPROXY=https://goproxy.cn,direct

# 在当前目录初始化创建main模块并自动解析下载依赖(构建完整模块 tidy完善go.mod)
RUN go mod init main && go mod tidy

# 执行编译命令 编译好的二进制是/apps/main
RUN go build -o /apps/main /apps/main.go

# 第二阶段:生成最终镜像
FROM alpine:latest

# 设置工作目录(创建并cd过去)
WORKDIR /root/

# 从第一阶段复制文件到第二阶段中
# --from 指定把builder阶段中的/app/myapp文件复制到当前镜像当前目录中(/root/main)
COPY --from=builder /apps/main .

# 设置时区为上海,并且创建全局访问的软链接
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo 'Asia/Shanghai' > /etc/timezone \
    && ln -s /root/main /usr/bin/main

# 设置编码
ENV LANG C.UTF-8

# 创建软链接 解决二进制无法执行问题 amd架构必须执行
# RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2

# 运行golang程序的命令
CMD main

3.构建镜像

docker build -f dockerfile -t g1 .

打包出来的镜像只有9m,符合alpine镜像大小

运行

docker run --rm -it g1