使用Dockerfile文件构建镜像

在Go项目路径下,创建一个新的Dockerfile文件,即可根据Dockerfile中的指令来构建对应的docker镜像。
本文中,我的项目结构如下:

.
├── Template
└── webForm.go

编写Dockerfile

# 导入基础镜像golang:alpine
FROM golang:alpine AS builder

# 设置环境变量
ENV GO111MODULE=auto \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64 \
    GOPROXY="https://goproxy.cn,direct"
	
# 创建并移动到工作目录(可自定义路径)
WORKDIR /build

# 将代码复制到容器中
COPY . .

# 将代码编译成二进制可执行文件,文件名为 WebApp
RUN go build -o WebApp .

# 移动到用于存放生成的二进制文件的 /dist 目录
WORKDIR /dist

# 将二进制文件从 /build 目录复制到这里
RUN cp /build/WebApp .

# 将项目用到的静态文件拷贝到镜像(如果没有可忽略该步骤)
COPY ./Template /dist/Template

# 声明服务端口
EXPOSE 9090

# 启动容器时运行的命令
CMD ["./WebApp"]

在终端移动到项目路径下,执行指令构建docker镜像

# goweb_app:v0为镜像名,可自行更改
docker build . -t goweb_app:v0

终端输出如下日志,即代表构建成功

Successfully built 6adbd92bed46
Successfully tagged goweb_app:v0

输入如下指令,启动镜像(端口号和镜像名根据自己的设置进行更改)

docker run -p 9090:9090 goweb_app:v0

可打开新终端,输入如下指令查看镜像

docker images

可以看到构建的镜像很大(我的高达300M),因为镜像包含了golang:alpine基础镜像。下面可以采用分阶段构建的方式优化。

分阶段构建docker镜像

上述构建方法中,会把基础镜像golang:alpine同时封装进去,而go应用在编译好以后可以不依赖编译器而运行。所以可以在项目编译以后构建一个不包含编译器的小镜像,然后从编译器中将编译好的二进制文件取出来进行封装,这样就可以构建不包含编译器的小镜像文件。

# 导入基础镜像golang:alpine
FROM golang:alpine AS builder

# 设置环境变量
ENV GO111MODULE=auto \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64 \
    GOPROXY="https://goproxy.cn,direct"
	
# 创建并移动到工作目录(可自定义路径)
WORKDIR /build

# 将代码复制到容器中
COPY . .

# 将代码编译成二进制可执行文件,文件名为 WebApp
RUN go build -o WebApp .

# 利用scratch创建一个小镜像
FROM scratch

# 从builder镜像中把/WebApp 拷贝到当前目录
COPY --from=builder /build/WebApp /

# 将项目用到的静态文件拷贝到镜像(如果没有可忽略该步骤)
COPY ./Template /Template

# 声明服务端口
EXPOSE 9090

# 启动容器时运行的命令
CMD ["/WebApp"]

同样的,在终端移动到项目路径下,执行指令构建docker镜像

# goweb_app:v0为镜像名,可自行更改
docker build . -t goweb_app:v0

终端输出如下日志,即代表构建成功

Successfully built 6adbd92bed46
Successfully tagged goweb_app:v0

输入如下指令,启动镜像(端口号和镜像名根据自己的设置进行更改)

docker run -p 9090:9090 goweb_app:v0

借助scratch创建的小镜像不包含编译器,因此很小(我的8M)。

注意:采用scratch方式构建的镜像不能使用sh指令

采用软件自动编写Dockerfile

借助goct工具可以实现Dockerfile的快速生成

首先安装一下工具

GOPROXY=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/goctl@latest

移动到项目所在路径,直接执行指令,快速构建镜像

# webForm.go改为你自己的项目文件
goctl docker -go webForm.go

也可以用指定方式镜像分阶段构建镜像(此处以 scratch为例)

goctl docker -base scratch -go webForm.go

生产的Dockerfile文件如下

FROM golang:alpine AS builder

LABEL stage=gobuilder

ENV CGO_ENABLED 0
ENV GOPROXY https://goproxy.cn,direct
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories

RUN apk update --no-cache && apk add --no-cache tzdata

WORKDIR /build

ADD go.mod .
ADD go.sum .
RUN go mod download
COPY . .
RUN go build -ldflags="-s -w" -o /app/webForm webForm.go


FROM scratch

COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
ENV TZ Asia/Shanghai

COPY --from=builder /app/webForm /

COPY ./Template /Template

CMD ["/webForm"]

经试验,采用该方式可以生成一个完整的Dockerfile框架,但是不一定可以直接使用。我构建好以后,由于没有自动导入静态文件Template导致不可用,自行在Dockerfile中修改添加了静态文件即可。

采用该方式构建,文件中务必包含go.mod和go.sun文件

参考资料

链接: https://www.cnblogs.com/kevinwan/p/16033634.html
链接: https://juejin.cn/post/6899041488806936583