从943MB到6.34kB,容器精简大挑战

容器给我们的生活带来了极大便利,人人都喜欢容器,然而容器也很耗空间,动辄几百兆,上G的镜像是普遍现象。本文我们就学习容器精简的案例,通过一系列的骚操作,最终将镜像的大小从943MB减小到了6.32k。

概述

容器是实践中用来解决与操作软件版本和包依赖相关的所有问题的有效途径。 人人都喜欢容器,但是用容器就得面对各式各样庞大和杂乱的镜像,如果空间有限,则很快就会被充满,实际上可以通过一些有效的策略来减小镜像大小。

基本步骤

一个Http应用容器,可以通过指定端口提供web服务。

不进行卷挂载。

原始方案

为了获得基准镜像大小,我们用node.js创建一个简单只提供index.js访问的简单的服务器:

index.js代码:

const fs = require('fs');const http = require('http');const server = http.createServer((req, res) => {res.writeHead(200, { 'content-type': 'text/html' })fs.createReadStream('index.html').pipe(res)})server.listen(port, hostname, () => {console.log(`Server: http://0.0.0.0:8080/`);});

然后,将该文件内置到一个镜像中,镜像基于Node官方基本镜像。

FROM node:14COPY . .CMD ['node', 'index.js']

编译

docker build -t cchttp:01 ./

镜像大小为943MB

精简基础镜像

镜像精简最常用,最简单,最明显的策略之一就是使用较小的基础图像。Node镜像中slim 变体(基于debian,但预安装的依赖项较少)和基于Alpine Linux的alpine变体 。

这两个基础镜像分别为node:14-slim 和 node:14-alpine ,其镜像大小分别减少到167MB 和 116MB 分别。

Docker由于镜像是分层叠加的,node.js需要依赖很多层的镜像,除了精简解决方案目前还没有其他变小的方法。

更换语言

为了进一步优化,需要使用运行时依赖项更少的编译语言。而这时候肯定会首先想到的是一个静态编译语言Golang,这是个常见而且不错的选择。在Golang中一个基本的Web服务代码如下:

web.go:

package mainimport ('fmt''log''net/http')func main() {fileServer := http.FileServer(http.Dir('./'))http.Handle('/', fileServer)fmt.Printf('Starting server at port 8080\n')if err := http.ListenAndServe(':8080', nil); err != nil {log.Fatal(err)}}

然后用golang官方基础镜像,将其打包到镜像:

FROM golang:1.14COPY . .RUN go build -o server .CMD ['./server']

基于golang的解决方案,镜像大小818MB,还是很大。

通过分析发现是由于golang基本镜像中安装了很多依赖包,这些依赖包在构建go软件时很有用,但不是每个运行时都需要的,所以可以从这儿着手优化。

多阶段构建

Docker支持多阶段构建的机制,可以很轻松在具有所有必要依赖项的环境中构建代码,然后将生成的可执行包直接打包到其他镜像中使用。这样就可以解决我们上一步遇到需要编译时工具和包,但是运行时不需要包,这样可以极大地减少镜像大小。

注意:Docker多阶段构建的机制是Docker 17.05引入的新特性,如果要使用该功能你需要将Docker版本升级到Docker 17.05及更高版本。

到多阶段构建dockerfile:

###编译###FROM golang:1.14-alpine AS builderCOPY . .RUN go build -o server .###运行###FROM alpine:3.12COPY --from=builder /go/server ./serverCOPY index.html index.htmlCMD ['./server']
Docker images

(⊙o⊙)哇,策略生效,这样生成的镜像只有13.2MB。

静态编译结合scratch基础镜像

13M的镜像已经很不错了,但是还有其他优化的技巧。在docker世界中还有几个基础镜像scratch ,那就是一个From 0 开始的基础镜像,使用该镜像没有任何依赖,完全从0开始,所以大小也就从0开始。Linux 有个发行版LFS,其全称是Linux From Scratch ,就是从零开始自己动手编译出一个完整的OS。这个scratch基础镜像也是这个意思。

为了让scratch基础镜像支持我们的web.go运行,我们需要在编译镜像中添加静态编译的标志,确保所有依赖都可以打包到运行镜像中:

### 编译###FROM golang:1.14 as builderCOPY . .RUN go build -o server \-ldflags '-linkmode external -extldflags -static' \-a web.go###运行###FROM scratchCOPY --from=builder /go/server ./serverCOPY index.html index.htmlCMD ['./server']

上面构建过程中,在代码链接过程中模式设置为external,-static链接外部链接器。

优化后,镜像大小为8.65MB。

最终大杀器——汇编语言

用Golang语言编写的程序,起码也有大概M级别的大小,10MB镜像应该已经到了可以精简的极限。但是还可以用其他技巧来大幅度精简大小,但是需要使用要给终极大杀器,那就是汇编语言,最终解决方案是使用一个汇编编写的全功能http服务器assmttpd,其源码托管在GitHub(github/nemasu/asmttpd)。

我们还使用多阶段编译方法,在ubuntu基础镜像中先编译其依赖项,然后在Scratch基础镜像中打包并运行。

###编译###FROM ubuntu:18.04 as builderRUN apt updateRUN apt install -y make yasm as31 nasm binutilsCOPY . .RUN make release###运行###FROM scratchCOPY --from=builder /asmttpd /asmttpdCOPY /web_root/index.html /web_root/index.htmlCMD ['/asmttpd', '/web_root', '8080']

产生的图像大小仅为6.34kB:

然后用该镜像运行一个容器:

docker run -it -p 10080:8080 cchttp:07

用curl访问一下:

curl -vv 127.0.0.1:10080

总结

本文我们探索了容器精简的各种方法和尝试。当然由于容器的功能简单,这些策略可能不发直接在实践中使用,但是可以作为容器调优的思路参考。

(0)

相关推荐

  • 10 个冷门但又非常实用的 Docker 使用技巧

    在平时的工作中,docker 接触得很多,除了经常使用的 docker run ,docker stop 等命令,docker 还有很多十分有用但是却不经常使用的命令,下面就来总结一下: 1. doc ...

  • docker学习前述

    什么东西都不懂直接来学习docker是有点难的,学习docker需要哪些技术基础做支撑? Linux(相关常用的命令要会) springboot docker学习大纲如下: Docker概述 Dock ...

  • Docker 镜像优化:从 1.16GB 到 22.4MB

    来源:架构头条(ID:ArchFront) Docker 是一个供软件开发人员和系统管理员使用容器构建.运行和与分享应用程序的平台.容器是在独立环境中运行的进程,它运行在自己的文件系统上,该文件系统是 ...

  • 医护默契大挑战,据说只有10%的医护得了满分!

    5.12国际护士节 你们用平凡书写着生命的感动, 用爱心为患者拂去满身的伤痛, 用笑容为患者增添前行的勇气: 你们将青春定格在燕尾帽下, 用奉献丈量着生命的长度, 你们是平凡又伟大的"白衣天 ...

  • 劳动“小达人”,闯关大挑战

    浙江省杭州市富春第七小学五年级的队员们,在校外红领巾劳动实践基地经历了一场与众不同的劳动体验.大家要通过不断闯关升级,才能成为劳动"小达人".我们赶快来看看,这场有趣的闯关劳动大挑 ...

  • 2020年家禽业面临的大趋势和大挑战!

    一.全球家禽业的发展趋势 根据联合国粮农组织的统计数据显示,畜牧业在二战之后发展迅速,肉蛋奶产品的增量速度显著加快. 在蛋产品领域中,东亚的产量增速在这50年中**明显,中国作为蛋产品生产大国起到了决 ...

  • #高考语文# #学科大挑战# 120句高...

    #高考语文# #学科大挑战# 120句高考语文古诗词,来看看你会几句吧有志者,事竟成,破釜沉舟,百二秦关终属楚 ​

  • 印度疫情从城市向农村地区蔓延,专家:防疫面临很大挑战

    尽管过去几天印度单日新增新冠肺炎确诊病例数逐步下降,但疫情形势依然严峻.近日来,疫情向农村地区蔓延的趋势引发多方担忧. 印度总理莫迪近日已表示,目前印度疫情正在从城市向农村地区快速蔓延.有专家指出,印 ...

  • 汉典重光:机器视觉实验室的大挑战

    加州大学伯克利分校的东亚图书馆很有纵深,这是全美三大东亚图书馆之一,九十万册藏书里四成都是中文书,还有不少甲骨文和拓片.中国以外,没几个图书馆有这水准. 第一次到这的李贝因此总感觉在穿越历史的&quo ...

  • 耐克未来一年面临10大挑战,棉花问题位列其中

    图片来源:AULO WHITAKER/REUTERS 耐克(Nike Inc., NKE)的股票评级被分析师下调,并被认为未来一年面临10项挑战,其中包括新进入行业的公司导致运动品类竞争加剧,以及加大 ...

  • 成都公园运维大挑战:三大老牌公园,还能迎来春天吗?

    新公园亮完相,老公园压轴登场,讲究撒! 前三篇请戳: 成都公园运维大挑战:四大超级选手,竟然没有大满贯!(上) 成都公园运维大挑战:四大超级选手,竟然没有大满贯!(下) 成都公园运维大挑战:三大文创公 ...

  • 成都公园运维大挑战:三大文创公园,到底谁是南波万?

    往期回顾: 成都公园运维大挑战:四大超级选手,竟然没有大满贯!(上) 成都公园运维大挑战:四大超级选手,竟然没有大满贯!(下) 成都公园运维挑战继续,本期UP君要带大家逛的,是近些年才出现的公园类别 ...