将Go程序打包成Docker镜像

2023-10-26

将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!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将Go程序打包成Docker镜像 的相关文章

随机推荐

  • 华为OD机试 - 数组二叉树(Java)

    题目描述 二叉树也可以用数组来存储 给定一个数组 树的根节点的值存储在下标1 对于存储在下标N的节点 它的左子节点和右子节点分别存储在下标2 N和2 N 1 并且我们用值 1代表一个节点为空 给定一个数组存储的二叉树 试求从根节点到最小的叶
  • 一行代码可以做些什么?

    点击蓝字 关注我们 众所周知 Python 是目前流行和易学的编程语言 2021 年 Python 获得了 TIOBE 编程指数的年度最受欢迎的编程语言 此外 它也连续蝉联了多个月的榜首 更值得一提的是 一些繁琐的任务 往往都可以用 Pyt
  • hadoop中的两个datanode节点的VERSION文件冲突,导致其中有一个datanode无法启动

    问题 分析 本来是有三个datanode才对 所以有一个datanode丢失 查看丢失的datanode的log日志 第一个报错 是datanode无法启动的报错日志 第二个报错 是因为datanode丢失 数据无法上传的报错 很奇怪的是
  • 2020年前端开发工具大全:50款热门的前端工具汇总

    今天跟大家分享一些目前比较热门新鲜度靠前的50款前端工具 希望对你有所帮助 下面和千锋广州小编一起来看看吧 一 构建工具 1 Parcel 地址 https parceljs org Parcel是一款极速零配置WEB应用打包工具 快速 几
  • Linux 根文件系统的挂载分析

    在介绍根文件系统挂载之前先介绍一些基础知识 initramfs 当linux内核启动后 会找到并执行第一个用户程序 一般是init 这个程序存在于文件系统当中 文件系统存在于设备上 但不知道init存在哪个设备上 于是有了内核命令列选项ro
  • 在Windows 10上安装WSL2

    TOC WSL2 在Windows10上安装 前提条件 是否支持Virtualization WSL2 是基于hyper V的 所以windows 机器必须支持虚拟化 如果是虚机的那就要支持嵌套的虚拟化 网上一堆看BIOS的太麻烦了 简单的
  • 【ffmpeg教程】【无损快速转换】两行代码 快速无损转换mkv flv视频文件 第一期

    ffmpeg教程 无损快速转换 两行代码 快速无损转换mkv flv视频文件 第一期 前言 环境准备 脚本编写 运行脚本 前言 视频版教程 无损快速转换 两行代码 快速无损转换mkv flv视频文件 导入Premiere教程 环境准备 工具
  • C#中得到两个数百分比 (转)

    此方法得到的百分比后小数太多 不行 double percent Convert ToDouble 2 Convert ToDouble 34 string result percent 100 ToString 得到的是5 8823529
  • 如何处理VS联合Qt没有ui_.h文件

    首先声明我使用的是VS2019 QT5 9 0 在初学VS联合QT时 发现自己VS中的资源管理器中没有ui h文件 在网上搜寻了一些解决方案 得出的大致结论就是 现在版本的VS中已经不会自动生成GeneratedFiles文件夹 那么其中的
  • 【数据结构与算法】深入浅出递归和迭代的通用转换思想

    深入浅出递归和迭代的通用转换思想 一般来说 能用迭代的地方就不要用递归 理论上讲 所有的递归和迭代之间都能相互转换 刷题碰到 一天一道LeetCode 130 Surrounded Regions所以来总结一下递归和迭代 一 何为迭代 首先
  • Microsoft365与Office到底啥区别?如何选择下载安装哪个版本?

    Microsoft 365 是一种订阅服务 可确保你始终拥有最新的 Microsoft 新式生产力工具 存在针对家庭和个人 中小型企业 大型企业 学校以及非营利组织的 Microsoft 365 计划 适用于家庭和商业的 Microsoft
  • 如何做好“向上管理”

    mghio 读完需要 10分钟 速读仅需 4 分钟 0 什么是 向上管理 向上管理用一句话来描述就是 在工作中为了取得更好的工作成果 有意识地配合你的领导一起工作的过程 请注意这里的有意识这个词 1 为什么要 向上管理 首先先来看看领导眼中
  • pthread_mutex_lock用法

    条件变量 条件变量是利用线程间共享的全局变量进行同步的一种机制 主要包括两个动作 一个线程等待 条件变量的条件成立 而挂起 另一个线程使 条件成立 给出条件成立信号 为了防止竞争 条件变量的使用总是和一个互斥锁结合在一起 条件变量是利用线程
  • 9.1-深度生成模型

    文章目录 图像处理 创作 PixelRNN 练习生成模型 自动编码器 宝可梦生成 图像处理 创作 有关generation model 这里有一篇很好的reference 在这篇reference里开头引用Richard Feynman的话
  • 【Tool】制作多系统启动盘

    前言 我一个U盘 64G的 总不能只装一个ubuntu就不能用了吧 所以百度一大堆多系统启动盘的软件 太难搞了 我灵机一动 我512G的硬盘都能分为两个区分别做系统区和存储区 为什么u盘不能分好几个区装好几系统呢 步骤 思路 把系统盘文件复
  • java smtp怎么开启_java-一个简单的本地SMTP

    java 一个简单的本地SMTP 我想测试用于发送电子邮件的Java代码 我不想使用任何商业邮件客户端或连接到任何外部邮件提供商 例如Gmail或Yahoo 我想知道是否存在允许用户配置虚拟电子邮件地址和服务器 本地 的软件 这些软件可以在
  • mac编程提示 Undefined symbol: _OBJC_CLASS_$_xxxx

    使用cocoa编程 编译提示报错 Showing All Issues Undefined symbol OBJC CLASS NSAlert 解决办法 link Binary With Libraries 添加 Foundation fr
  • TNS-12542: TNS: 地址已被占用

    TNS 12542 TNS 地址已被占用 监听该对象时出错 DESCRIPTION ADDRESS PROTOCOL TCP HOST HKY PORT 1521 TNS 12560 TNS 协议适配器错误 TNS 00512 地址已在使用
  • rocketMq中文文档

    title 用户指引 date 2017 12 29 categories 文档翻译 为什么是RocketMQ 动机 在早期阶段 我们在ActiveMQ 5 x 早于5 3 的基础上构建我们的分布式消息中间件 我们的跨国业务使用它来实现异步
  • 将Go程序打包成Docker镜像

    将Go程序打包成Docker镜像 1 Go程序 hello go 文件的内容 package main import fmt func main fmt Println hello world 2 编写Dockerfile文件 FROM g