docker 最小镜像(scratch:latest)
一、简介:
Scratch镜像很赞,它简洁、小巧而且快速,它没有bug、安全漏洞、延缓的代码或技术债务。除了被Docker添加了metadata (译注:元数据为描述数据的数据)之外,它基本上是空的。
我们在使用Dockerfile构建docker镜像时,一种方式是使用官方预先配置好的容器镜像。优点是我们不用从头开始构建,节省了很多工作量,但付出的代价是需要下载很大的镜像包。
如果我们的需求是在构建一个符合我们实际业务需求的Docker镜像的前提下,确保镜像尺寸尽可能的小,应该怎么做呢?
思路是使用空镜像scratch,可以说是真正的从零开始构建属于自己的镜像
二、跨越平台:从零开始
我们知道,构建镜像的过程一般都是从父镜像开始的,但父镜像依赖于指令集架构。所以有没有可能我们跨越平台架构来构建精简的镜像呢?那就需要用到scratch了。
为镜像进一步减重,减到尽可能的小,把所有不必要的东西都拆掉:仅仅保留能支撑我们应用运行的必要库,命令,其余的一律不纳入目标镜像。 当然不仅仅是Size上的原因,小镜像还有额外的优势,比如:内存占用小,启动速度快,更加高效;因为它不包含额外不必要的工具,所以它更安全,不会因为其他不必要的工具、库的漏洞而被攻击,减少了“攻击面”。
scratch构建镜像精简到可以只在scratch上面加一层可执行的二进制文件。
三、容器镜像结构原理
- scratch:docker 中最基础的镜像,可以简单的理解为 kernel ,debian、ubuntu 和 centos 等都基于 scratch 之上
- base:不依赖其他镜像,从 scratch 构建,base镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS等;其他镜像(nginx\tomcat)可以之为基础进行扩展
四、Linux 操作系统由内核空间和用户空间组成
- 内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。
- 用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。
- 对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。
- base 镜像只是在用户空间与发行版一致,kernel 版本与发型版是不同的。
- 如果 本机系统为是 Ubuntu 16.04,内核为kernel:4.x.x,那么在 CentOS7 容器中使用的实际是是本机 4.x.x 的 kernel。
五、使用方法
1、制作大小为0 的镜像
tar cv --files-from /dev/null | docker import - scratch
2、编译go程序
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags " -w" -o ./sg-admin main.go
3、编写 Dockerfile文件
macbook:01 houchaoyue$ cat Dockerfile
FROM scratch
ADD admin /
CMD ["/admin"]
4、生成对应的容器镜像
macbook:01 houchaoyue$ docker build -t sg-admin:v1 .
5、运行容器即可
docker run --name sg-admin -d sg-admin:v1
注意事项: 1)在构建二进制可执行文件的时候,需要进行静态编译链接,因为scratch中没有我们需要的动态链接库 2) 在 macbook 中只能编译时只能指定 linux 系统才能正常使用 3)如果你的Go应用程序需要子处理用到其他程序(例如,git)或者它几乎使用任何使用CGo的库(这些库几乎总是依赖于libc,如果不是其他库),则此方法将不起作用。
用途 1)scratch 是一个空镜像,使用docker 把main 函数拉起来,服务小,做升级,降级,版本管理的优势大。 2)选择scratch的最大原因是安全性-减少攻击面。
遇到的问题: 1、不需要使用rootfs也可运行golang编译的二进制文件。 虽然 macOS 内核结合了微内核(Mach)和宏内核(BSD)的特性,但 Linux 只是一个宏内核。宏内核负责管理 CPU、内存、进程间通信、设备驱动程序、文件系统和系统服务调用( LCTT 译注:原文为 system server calls,但结合 Linux 内核的构成,译者认为这里翻译成系统服务调用更合适,即 system service calls)。容器运行使用的是本机的宏内核,在宏内核之上可运行rootfs,rootfs中存在的是一些常见的使用命令,因此可运行go程序
|