将Go程序打包成Docker镜像

将Go程序打包成Docker镜像

1、Go程序

hello.go 文件的内容:

package main

import "fmt"

func main() {
    fmt.Println("hello world!")
}

2、编写Dockerfile文件

FROM golang:alpine
WORKDIR /build
COPY hello.go .
RUN go build -o hello hello.go
CMD ["./hello"]

3、生成镜像

$ docker build -t hello:v1 .
Sending build context to Docker daemon  4.096kB
Step 1/5 : FROM golang:alpine
 ---> 9e57a8e81959
Step 2/5 : WORKDIR /build
 ---> Running in 8f2b5f3a7a67
Removing intermediate container 8f2b5f3a7a67
 ---> 5eec1827e58b
Step 3/5 : COPY hello.go .
 ---> 40fa3fb77c75
Step 4/5 : RUN go build -o hello hello.go
 ---> Running in 6be6b967a873
Removing intermediate container 6be6b967a873
 ---> ae169d199066
Step 5/5 : CMD ["./hello"]
 ---> Running in b62da09aad56
Removing intermediate container b62da09aad56
 ---> 68296087b8d0
Successfully built 68296087b8d0
Successfully tagged hello:v1

查看构建过程:

$ docker history hello:v1
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
68296087b8d0   18 minutes ago   /bin/sh -c #(nop)  CMD ["./hello"]              0B
ae169d199066   18 minutes ago   /bin/sh -c go build -o hello hello.go           26.5MB
40fa3fb77c75   19 minutes ago   /bin/sh -c #(nop) COPY file:72d9bcc020ef9348…   76B
5eec1827e58b   19 minutes ago   /bin/sh -c #(nop) WORKDIR /build                0B
9e57a8e81959   12 days ago      /bin/sh -c #(nop) WORKDIR /go                   0B
<missing>      12 days ago      /bin/sh -c mkdir -p "$GOPATH/src" "$GOPATH/b…   0B
<missing>      12 days ago      /bin/sh -c #(nop)  ENV PATH=/go/bin:/usr/loc…   0B
<missing>      12 days ago      /bin/sh -c #(nop)  ENV GOPATH=/go               0B
<missing>      12 days ago      /bin/sh -c set -eux;  apk add --no-cache --v…   247MB
<missing>      12 days ago      /bin/sh -c #(nop)  ENV GOLANG_VERSION=1.20.5    0B
<missing>      12 days ago      /bin/sh -c #(nop)  ENV PATH=/usr/local/go/bi…   0B
<missing>      12 days ago      /bin/sh -c apk add --no-cache ca-certificates   516kB
<missing>      12 days ago      /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      12 days ago      /bin/sh -c #(nop) ADD file:1da756d12551a0e3e…   7.33MB

主要是:

/bin/sh -c go build -o hello hello.go

/bin/sh -c set -eux; apk add --no-cache

这两个过程比较占用空间。

4、查看镜像

# 发现镜像占用空间218M
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
hello        v1        68296087b8d0   3 seconds ago   281MB
golang       alpine    9e57a8e81959   12 days ago     254MB

5、运行

$ docker run -it hello:v1
hello world!
$ docker run -it hello:v1 ls -l /build
total 1812
-rwxr-xr-x    1 root     root       1847520 Jun 27 07:59 hello
-rw-r--r--    1 root     root            76 Jun 27 07:31 hello.go

我们生成的镜像运行没有问题,只是生成的镜像占用空间比较大。

我们可以尝试先将 hello.go 进行编译,然后再拷贝进去。

6、重新构造镜像

# 提前编译好go文件
$ go build hello.go
# 这里我们不在需要编译go文件,因此将golang:alpine换为alpine
FROM alpine
WORKDIR /build
COPY hello .
CMD ["./hello"]
# 此次生成镜像速度特别快
$ docker build -t hello:v2 .
Sending build context to Docker daemon  1.943MB
Step 1/4 : FROM alpine
 ---> c1aabb73d233
Step 2/4 : WORKDIR /build
 ---> Running in 29fecf779165
Removing intermediate container 29fecf779165
 ---> 45f7c46a90af
Step 3/4 : COPY hello .
 ---> 48b0b089166a
Step 4/4 : CMD ["./hello"]
 ---> Running in 1a97a57604e1
Removing intermediate container 1a97a57604e1
 ---> aadbd54c2f2d
Successfully built aadbd54c2f2d
Successfully tagged hello:v2

发现重新生成的镜像所占用的空间变小了。

# 生成的镜像的大小只有9.27MB
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
hello        v2        aadbd54c2f2d   40 seconds ago   9.27MB
hello        v1        68296087b8d0   35 minutes ago   281MB
golang       alpine    9e57a8e81959   12 days ago      254MB
alpine       latest    c1aabb73d233   12 days ago      7.33MB

查看生成过程:

$ docker history hello:v2
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
aadbd54c2f2d   About a minute ago   /bin/sh -c #(nop)  CMD ["./hello"]              0B
48b0b089166a   About a minute ago   /bin/sh -c #(nop) COPY file:705516e6f5c7bf5e…   1.94MB
45f7c46a90af   About a minute ago   /bin/sh -c #(nop) WORKDIR /build                0B
c1aabb73d233   12 days ago          /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      12 days ago          /bin/sh -c #(nop) ADD file:1da756d12551a0e3e…   7.33MB

运行:

$ docker run -it hello:v2

$ docker run -it hello:v2 ls -l /build
total 1896
-rwxr-xr-x    1 root     root       1937447 Jun 27 08:12 hello

综合上面的两个步骤我可以写出一个完整的Dockerfile。

7、综合Dockerfile

# 第一步编译go文件
FROM golang:alpine AS builder
WORKDIR /build
ADD go.mod .
COPY . .
RUN go build -o hello hello.go

# 第二步部生成镜像
FROM alpine
WORKDIR /build
COPY --from=builder /build/hello /build/hello
CMD ["./hello"]

生成:

$ docker build -t hello:v3 .
Sending build context to Docker daemon  1.943MB
Step 1/9 : FROM golang:alpine AS builder
 ---> 9e57a8e81959
Step 2/9 : WORKDIR /build
 ---> Using cache
 ---> 5eec1827e58b
Step 3/9 : ADD go.mod .
 ---> d59e6bcf895e
Step 4/9 : COPY . .
 ---> 44cbf7b9c5b6
Step 5/9 : RUN go build -o hello hello.go
 ---> Running in 27ecc4c5e2d7
Removing intermediate container 27ecc4c5e2d7
 ---> b2313317a6d1
Step 6/9 : FROM alpine
 ---> c1aabb73d233
Step 7/9 : WORKDIR /build
 ---> Using cache
 ---> 45f7c46a90af
Step 8/9 : COPY --from=builder /build/hello /build/hello
 ---> 58a1c5d9a53d
Step 9/9 : CMD ["./hello"]
 ---> Running in 9027de2e8dbc
Removing intermediate container 9027de2e8dbc
 ---> 2313f46cff16
Successfully built 2313f46cff16
Successfully tagged hello:v3

查看生成的镜像:

# 这里会生成一个中间镜像,如果不想要这个中间镜像,可以在build的时候添加参数--rm
# docker build -t hello:v3 --rm .
# 如果编译和平台相关的可以添加参数--platform linux/amd64
# docker build -t hello:v3 --rm --platform linux/amd64 .
$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
hello        v3        2313f46cff16   30 seconds ago   9.18MB
<none>       <none>    b2313317a6d1   31 seconds ago   283MB
hello        v2        aadbd54c2f2d   6 minutes ago    9.27MB
hello        v1        68296087b8d0   41 minutes ago   281MB
golang       alpine    9e57a8e81959   12 days ago      254MB
alpine       latest    c1aabb73d233   12 days ago      7.33MB

查看生成过程:

$ docker history hello:v3
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
2313f46cff16   About a minute ago   /bin/sh -c #(nop)  CMD ["./hello"]              0B
58a1c5d9a53d   About a minute ago   /bin/sh -c #(nop) COPY file:4d5797c47f0fede3…   1.85MB
45f7c46a90af   6 minutes ago        /bin/sh -c #(nop) WORKDIR /build                0B
c1aabb73d233   12 days ago          /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>      12 days ago          /bin/sh -c #(nop) ADD file:1da756d12551a0e3e…   7.33MB

运行:

$ docker run -it hello:v3
hello world!

$[root@omdev om]# docker run -it hello:v3 ls -l /build
total 1808
-rwxr-xr-x    1 root     root       1847520 Jun 27 08:40 hello

关于多步构建镜像请参考:

https://docs.docker.com/build/building/multi-stage/

8、go工具生成Dockerfile

# 安装
$ go install github.com/zeromicro/go-zero/tools/goctl@latest
# 生成dockerfile
$ goctl docker -go hello.go
Done.

查看生成的内容:

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/hello hello.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

WORKDIR /app
COPY --from=builder /app/hello /app/hello

CMD ["./hello"]
  • 默认禁用了 cgo
  • 启用了 GOPROXY 加速 go mod download
  • 去掉了调试信息 -ldflags="-s -w" 以减小镜像尺寸
  • 安装了 ca-certificates,这样使用 TLS 证书就没问题了
  • tzdata 在 builder 镜像安装,并在最终镜像只拷贝了需要的时区
  • 自动设置了本地时区,这样我们在日志里看到的是北京时间了

如果缺 go.sum 文件则新建一个即可。

生成镜像:

docker build -t hello:v4 .
Sending build context to Docker daemon   5.12kB
Step 1/19 : FROM golang:alpine AS builder
 ---> 9e57a8e81959
Step 2/19 : LABEL stage=gobuilder
 ---> Running in 6cd172282921
Removing intermediate container 6cd172282921
 ---> 115f5d1cdcf9
Step 3/19 : ENV CGO_ENABLED 0
 ---> Running in 07038c7d7de2
Removing intermediate container 07038c7d7de2
 ---> 389710709d4d
Step 4/19 : ENV GOPROXY https://goproxy.cn,direct
 ---> Running in 2973c66264f1
Removing intermediate container 2973c66264f1
 ---> 9686c8997bfa
Step 5/19 : RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
 ---> Running in 10dd563aa985
Removing intermediate container 10dd563aa985
 ---> c64df5014c82
Step 6/19 : RUN apk update --no-cache && apk add --no-cache tzdata
 ---> Running in f1711c396d56
fetch https://mirrors.aliyun.com/alpine/v3.18/main/x86_64/APKINDEX.tar.gz
fetch https://mirrors.aliyun.com/alpine/v3.18/community/x86_64/APKINDEX.tar.gz
v3.18.2-172-g9cc21627ccc [https://mirrors.aliyun.com/alpine/v3.18/main]
v3.18.2-175-g8680db500bf [https://mirrors.aliyun.com/alpine/v3.18/community]
OK: 20062 distinct packages available
fetch https://mirrors.aliyun.com/alpine/v3.18/main/x86_64/APKINDEX.tar.gz
fetch https://mirrors.aliyun.com/alpine/v3.18/community/x86_64/APKINDEX.tar.gz
(1/1) Installing tzdata (2023c-r1)
OK: 11 MiB in 17 packages
Removing intermediate container f1711c396d56
 ---> 65159ffacc89
Step 7/19 : WORKDIR /build
 ---> Running in 87ce395807d7
Removing intermediate container 87ce395807d7
 ---> 246414a07ddf
Step 8/19 : ADD go.mod .
 ---> f7458fabf27d
Step 9/19 : ADD go.sum .
 ---> baba6bcce93f
Step 10/19 : RUN go mod download
 ---> Running in 6fc5c82c0e59
go: no module dependencies to download
Removing intermediate container 6fc5c82c0e59
 ---> 8efabaedc150
Step 11/19 : COPY . .
 ---> 3a03d14c48ba
Step 12/19 : RUN go build -ldflags="-s -w" -o /app/hello hello.go
 ---> Running in f91a7d951206
Removing intermediate container f91a7d951206
 ---> e0fb09ae5bdf
Step 13/19 : FROM scratch
 --->
Step 14/19 : COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
 ---> 39c3a35c7da3
Step 15/19 : COPY --from=builder /usr/share/zoneinfo/Asia/Shanghai /usr/share/zoneinfo/Asia/Shanghai
 ---> 2ca366a09bfc
Step 16/19 : ENV TZ Asia/Shanghai
 ---> Running in 4ef75e26b3d3
Removing intermediate container 4ef75e26b3d3
 ---> 07e58484ab0c
Step 17/19 : WORKDIR /app
 ---> Running in 76de31d5eeca
Removing intermediate container 76de31d5eeca
 ---> 14a13570ccaf
Step 18/19 : COPY --from=builder /app/hello /app/hello
 ---> 36a202422d79
Step 19/19 : CMD ["./hello"]
 ---> Running in 1fbac50eb0aa
Removing intermediate container 1fbac50eb0aa
 ---> 50943134a8b0
Successfully built 50943134a8b0
Successfully tagged hello:v4

查看生成的镜像:

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
hello        v4        50943134a8b0   50 seconds ago   1.44MB
<none>       <none>    e0fb09ae5bdf   52 seconds ago   281MB
hello        v3        2313f46cff16   13 minutes ago   9.18MB
<none>       <none>    b2313317a6d1   13 minutes ago   283MB
hello        v2        aadbd54c2f2d   19 minutes ago   9.27MB
hello        v1        68296087b8d0   54 minutes ago   281MB
golang       alpine    9e57a8e81959   12 days ago      254MB
alpine       latest    c1aabb73d233   12 days ago      7.33MB

这里生成的镜像更小。

查看生成过程:

$ docker history hello:v4
IMAGE          CREATED              CREATED BY                                      SIZE      COMMENT
50943134a8b0   About a minute ago   /bin/sh -c #(nop)  CMD ["./hello"]              0B
36a202422d79   About a minute ago   /bin/sh -c #(nop) COPY file:19d791be1a41b87f…   1.23MB
14a13570ccaf   About a minute ago   /bin/sh -c #(nop) WORKDIR /app                  0B
07e58484ab0c   About a minute ago   /bin/sh -c #(nop)  ENV TZ=Asia/Shanghai         0B
2ca366a09bfc   About a minute ago   /bin/sh -c #(nop) COPY file:9b62331971fdb1f9…   561B
39c3a35c7da3   About a minute ago   /bin/sh -c #(nop) COPY file:cee95daa6036230f…   215kB

运行:

$ docker run -it hello:v4
hello world!
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值