创建最小的Go docker 镜像

简介:

虽然曾有一些文章介绍了如何创建一个最小的Go Docker镜像,我也曾写过一篇文章,但是随着Go的新的版本的发布, 以及docker本身的进化,有些技巧已经发生了变化, 本文介绍了最新的创建超小的Go镜像的方法。

一个简单Go程序的镜像

首先让我们创建一个很简单的Go程序:


1package main
2import "fmt"
3func main() {
4 fmt.Println("hello world")
5}

运行下面的命令会创建一个超小的镜像, 这是我们的第一种方式:

1GOOS=linux CGO_ENABLED=0 go build -ldflags="-s -w" -o app app.go && tar c app | docker import - app:latest
下一节介绍其中的编译参数

查看镜像, 生成的镜像只有 1.21MB


1# docker images app
2REPOSITORY TAG IMAGE ID CREATED SIZE
3app latest b716e13758cd 11 seconds ago 1.21MB

这命令将编译、打包、输入镜像集成到一条命令了。

第二种方式是使用一个Dockerfile文件:


1FROM scratch
2ADD app /
3CMD ["/app"]

运行下面的命令创建一个镜像:

1docker build -t app2 .

查看生成的镜像, 也是 1.21MB:


1# docker images app2
2REPOSITORY TAG IMAGE ID CREATED SIZE
3app2 latest 4e2af2ffb695 4 seconds ago 1.21MB

第三种方式是利用Docker的 multistage 功能,在镜像中编译,Dockerfile文件:


1Dockerfile.multistage
2docker build -t app3 -f Dockerfile.multistage .

查看生成的镜像, 也是``:


1# docker images app3
2REPOSITORY TAG IMAGE ID CREATED SIZE
3app3 latest 9177859dad64 16 seconds ago 1.21MB

你可以结合你的情况选择一种生成镜像的方式。

编译Go程序

上面的例子中我们使用下面的命令编译Go程序:

1GOOS=linux CGO_ENABLED=0 go build -ldflags="-s -w" -o app app.go

你可能在其它一些文章中还看到installsuffix参数:

1GOOS=linux CGO_ENABLED=0 go build -ldflags="-s -w" -installsuffix cgo -o app app.go

自Go 1.10以后,你不必再使用installsuffix参数(或许更早的版本),Go的核心开发人员Ian Lance Taylor已经确认了这一点。

你可能有人还使用-a参数,它强制重新编译相关的包,一般你不会使用它。

-s 忽略符号表和调试信息,-w忽略DWARF符号表,通过这两个参数,可以进一步减少编译的程序的尺寸,更多的参数可以参考go link, 或者 go tool link -help(另一个有用的命令是go tool compile -help)。

你也可以使用strip工具对编译的Go程序进行裁剪。

本身Go是静态编译的, 对于CGO, 如果设置CGO_ENABLED=0,则完全静态编译,不会再依赖动态库。

如果设置CGO_ENABLED=0,并且你的代码中使用了标准库的net包的话,有可能编译好的镜像无法运行,报sh: /app: not found的错误,尽管/app这个文件实际存在,并且如果讲基础镜像换为centos或者ubuntu的话就能执行。这是一个奇怪的错误,原因在于:

默认情况下net包会使用静态链接库, 比如libc

知道了原因,解决办法也很简单,就是完全静态链接或者在基础镜像中加入libc库。

下面是几种解决办法:

设置 CGO_ENABLED=0 编译是使用纯go的net: go build -tags netgo -a -v 使用基础镜像加glibc(或等价库musl、uclibc), 比如 busybox:glibc、alpine + RUN apk add --no-cache libc6-compat、frolvlad/alpine-glibc

有的同学说了,我代码中确实必须使用CGO,因为需要依赖一些C/C++的库。目前没有对应的Go库可替代, 那么可以使用-extldflags "-static",go tool link help介绍了extldflags的功能:

-extldflags flags

Set space-separated flags to pass to the external linker.

-static means do not link against shared libraries

基础镜像

其实前面已经列出了一些常用的基础镜像:

scratch: 空的基础镜像,最小的基础镜像

busybox: 带一些常用的工具,方便调试, 以及它的一些扩展busybox:glibc

alpine: 另一个常用的基础镜像,带包管理功能,方便下载其它依赖的包

显然。 你应该只在编译阶段使用Go的镜像,这样才能将你的镜像减小到最小。


原文发布时间为:2018-10-31

本文作者:smallnest 

本文来自云栖社区合作伙伴“Golang语言社区”,了解相关信息可以关注“Golang语言社区”。

相关文章
|
1月前
|
存储 JSON 数据格式
docker load 后镜像名称为空的问题解决
Docker在容器化应用程序时提供了强大的镜像管理功能,但也可能在某些操作中遇到如镜像名称为空的问题。通过理解问题的成因并采取适当的解决方案,如正确保存和加载镜像、手动修复标签等,可以有效避免和解决这一问题。通过本文提供的指导,您可以确保在使用Docker进行镜像操作时更为顺利,并提高容器管理的效率。
178 82
|
2天前
|
Docker 容器 Perl
云效flow构建docker镜像更换apt源为阿里镜像源
在 Dockerfile 中添加命令以更换 Debian 源为阿里云镜像,加速容器内软件包下载。核心命令通过 `sed` 实现源地址替换,并更新 apt 软件源。其中 `cat` 命令用于验证替换是否成功,实际使用中可删除该行。
68 31
|
10天前
|
监控 Java Go
无感改造,完美监控:Docker 多阶段构建 Go 应用无侵入观测
本文将介绍一种基于 Docker 多阶段构建的无侵入 Golang 应用观测方法,通过此方法用户无需对 Golang 应用源代码或者编译指令做任何改造,即可零成本为 Golang 应用注入可观测能力。
|
2天前
|
Ubuntu Linux 网络安全
Ubuntu Docker镜像:支持systemctl、SSH、VNC
总的来说,创建一个支持systemctl、SSH和VNC的Ubuntu Docker镜像需要一些技术知识,但是通过学习和实践,我们可以掌握这些技术。这将使我们能够更有效地使用Docker,更好地管理我们的应用程序和服务。CentOS系统中的日志文件位置和管理
36 17
|
7天前
|
Ubuntu 安全 网络安全
Docker镜像:Ubuntu支持systemctl、SSH和VNC
总的来说,Docker提供了一个灵活且强大的方式来创建和运行自定义的Ubuntu镜像。通过理解和使用Dockerfile,你可以轻松地创建一个支持systemctl、SSH和VNC的Ubuntu镜像。
90 21
|
19天前
|
NoSQL Redis 数据库
Docker平台上的Redis镜像运行
这就是如何在Docker平台上运行Redis镜像的全部过程。走进Docker和Redis的世界,探索更多可能!
75 10
|
25天前
|
安全 API 算法框架/工具
大模型文件Docker镜像化部署技术详解
大模型文件Docker镜像化部署技术详解
181 2
|
1月前
|
SQL Linux 数据库
YashanDB Docker镜像制作
本文介绍了使用Docker部署YashanDB数据库的方法及其优势。相比传统部署方式,Docker简化了环境配置,实现一键部署,确保软件在不同环境中一致运行。文章详细讲解了数据库镜像与容器的概念、Dockerfile的构建流程,以及如何通过Dockerfile定制YashanDB镜像。此外,还演示了镜像的发布过程,包括推送至阿里云容器镜像服务(ACR)。最后,探讨了容器启动时的初始化脚本设置和数据文件复用方法,满足客户对数据库自动化初始化和数据持久化的需求。
|
2月前
|
消息中间件 Kafka 流计算
docker环境安装kafka/Flink/clickhouse镜像
通过上述步骤和示例,您可以系统地了解如何使用Docker Compose安装和配置Kafka、Flink和ClickHouse,并进行基本的验证操作。希望这些内容对您的学习和工作有所帮助。
287 28
|
2月前
|
存储 运维 应用服务中间件
Docker Image即Docker镜像
Docker 镜像是 Docker 容器的基础,包含了运行应用程序所需的一切。通过 Dockerfile 可以方便地创建自定义镜像,并且利用 Docker 提供的命令可以轻松管理和使用这些镜像。掌握 Docker 镜像的创建、管理和使用,是进行容器化应用开发和部署的基础技能。希望本文能帮助读者更好地理解 Docker 镜像的概念和操作,提高开发和运维效率。
159 13

热门文章

最新文章

下一篇
oss创建bucket