常用做法
基于 golang 官方基础镜像打包,Dockerfile如下:
1 | # 基于 golang 官方基础镜像打包 |
但是最终 docker build 出来的镜像高达300多M, 这是由于 golang 这个基础镜像中的工具链及其依赖项(git,mercurial 等)重达几百MB,而这一部分我们在运行的时候是不需要的。
因此,我们需要对基础镜像进行精简。
精简镜像
使用 scratch
该镜像是一个空的镜像,可以用于构建 busybox 等超小镜像,可以说是真正的从零开始构建属于自己的镜像。在此基础镜像上运行的应用程序只能访问内核,尽管Go宣称自己只需要Linux内核,但是我们在真实的项目中或多或少会有其他依赖项,比如 我们项目会用到 CGO 等等。所以在构建 Golang 项目是,一般不建议直接采用 scratch 做基础镜像,否则你需要在 Dockerfile 中手动加载很多依赖项。
1 | # 基于 scratch 官方基础镜像打包 |
使用 alpine
Alpine 操作系统是一个面向安全的轻型 Linux 发行版。它不同于通常 Linux 发行版,alpine 采用了 musl libc 和 busybox 以减小系统的体积和运行时资源消耗,但功能上比 busybox 又完善的多,因此得到开源社区越来越多的青睐。
Alpine Docker 镜像也继承了 Alpine Linux 发行版的这些优势。相比于其他 Docker 镜像,它的容量非常小,仅仅只有 5 MB 左右(对比 Ubuntu 系列镜像接近 200 MB),且拥有非常友好的包管理机制。官方镜像来自 docker-alpine 项目。目前 Docker 官方已开始推荐使用 Alpine 替代之前的 Ubuntu 做为基础镜像环境。
Alpine 和其他通用 Linux 发行版对于 Golang 编译出来的可执行文件要求有所不同,Alpine 要求可执行文件必须是静态链接的可执行文件。所以在编译 Golang 时需要添加 -tags netgo ,来生成静态链接的可执行文件。
1 | # 基于 alpine 官方基础镜像打包 |
但是对 C 的支持不太好。
在 Alpine Docker 镜像上运行 cgo 项目会出现问题,提示一下问题:
1 | panic: standard_init_linux.go:175: exec user process caused "no such file or directory" |
原因是当 cgo 开启时,默认是按照动态库的方式来链接 so 文件的,但 alpine 只支持静态链接,所以会出错。
解决方案有两种:
通过设置 CGO_ENABLED=0 来解决,此时 cgo 也不可用了
调用 go build –ldflags “-extldflags -static” ,来让gcc使用静态编译可以解决问题
使用 ubuntu
ubuntu 镜像
1 | # 基于 ubuntu 官方基础镜像打包 |
最佳实践
多层构建方式
FROM golang:1.12
用对go功能比较齐全镜像编译源程序,生成可执行文件
FROM ubuntu
用精简镜像作为最终的容器的镜像
拷贝可执行文件到容器内
打包生成最终的镜像
Dockerfile:
1 | # 打包依赖阶段使用golang作为基础镜像 |
v1.5.2