Dockerfile于分层编排 Go 程序并复制项目配置文件

14 min read
FROM golang:1.19-alpine as builder
WORKDIR /app
ADD go.mod .
ADD go.sum .
RUN go mod download

ADD . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest as prod
RUN apk update && apk add --no-cache ca-certificates
WORKDIR /app
COPY --from=builder /app/app .
#COPY config/config.yaml .

CMD ["./app"]

这个 Dockerfile 由两个阶段组成。第一个阶段使用 golang:1.17-alpine 作为基础镜像,设置工作目录为 /app,并将项目的所有文件复制到工作目录中。然后使用 go mod download 下载依赖库,并使用 go build 命令编译出可执行文件。

第二个阶段使用 alpine:3.15 作为基础镜像,并安装了 ca-certificates。然后将工作目录设置为 /app,从第一个阶段中复制编译出来的可执行文件 app 和配置文件 config/config.yaml 到镜像中,并设置容器启动时的默认命令为 ./app

注意,在第二个阶段中使用了 --from=build 参数来指定复制源,这意味着只复制第一个阶段构建出来的文件,而不会复制构建环境中的任何文件,从而实现了分层编排。

对应的 docker-compose.yaml

version: '3'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./config:/app/config
    ports:
      - "8080:8080"

指令RUN go mod download执行的时候,会构建一层缓存,包含了该项所有的依赖。之后再次提交的代码中,若是go.modgo.sum没有变化,就会直接使用该缓存,起到加速构建的作用,也不用重复的去外网下载依赖了。若是这两个文件发生了变化,就会重新构建这个缓存分层。

 => CACHED [builder 2/7] WORKDIR /app                                                                                                                                                                                        0.0s
 => CACHED [builder 3/7] ADD go.mod .                                                                                                                                                                                        0.0s
 => CACHED [builder 4/7] ADD go.sum .                                                                                                                                                                                        0.0s
 => CACHED [builder 5/7] RUN go mod download