静态WEB容器镜像最小化实践
在现代的B/S架构应用中,我们会做前后端分离,某些前端Web服务会将编译完成的静态文件放到一个web服务器进行部署。例如,我的博客也是基于Hugo编译的静态文件来进行部署的。
那在容器化部署模式下,我们需要基于一个web服务的基础容器(镜像)将静态文件构建成站点或者Web服务的容器镜像来进行部署。在Docker开发最佳实践中,我们应该尽量保持镜像足够小(Size大小)。因此,我们应该尽量选择满足我们需求的web服务基础镜像足够小。
大部分情况下,我们会选择Nginx作为我们的web服务器,一开始我也是这么选择的,因为社区在Docker Hub上为我们提供了开箱即用的容器镜像,下面来看看我用来构建静态web服务的过程。
Nginx On Alpine
我们知道在容器构建的实践中,我们可以选择基于AlpineLinux为分发系统的镜像,其比其他(例如 ubuntu, centos等)的镜像会小很多。因此一开始我们也是选择基于Alpine的nginx镜像,例如 nginx:1.22-alpine。
$ docker image pull nginx:1.22-alpine
$ docker image ls | grep nginx
nginx 1.22-alpine 23.5MB
可以看到其大小为 23.5MB 。
基于该惊醒构建我的博客的发布镜像
FROM mengzyou/hugo:0.106 AS builder
COPY --chown=hugo:hugo . /home/hugo/app
RUN hugo
FROM nginx:1.22-alpine
COPY --from=builder /home/hugo/app/public/ /usr/share/nginx/html
$ docker build -t myblog:nginx .
$ docker image ls --format "{{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep myblog
myblog nginx 29MB
构建出来而最终交付镜像的大小为 29MB 。
Easyhttpd On Alpine
后来,我发现了一个用GoLang编写的轻量级web服务器 - easyhttpd,于是我Fork了该项目,编写了一个Dockerfile来构建该web服务器的镜像,具体可查看该文件内容。
镜像我已发布在mengzyou/easyhttpd。
$ docker image ls --format "{{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep easyhttpd
mengzyou/easyhttpd v0.0.1 13.7MB
镜像大小为 13.7MB,比 nginx:alpine 的镜像小了十几MB。使用该镜像构建来构建我的博客站点
...
FROM mengzyou/easyhttpd:v0.0.1
COPY --from=builder --chown=http:www /home/hugo/app/public/ /srv/www
$ docker image ls --format "{{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep myblog
myblog nginx 29MB
myblog ehttpd 19.1MB
得到的应用镜像大小为 19.1MB ,进一步减少了应用的镜像大小。
BusyBox Httpd
最近看到了一个国外的博客文章,可以构建一个只有 ~155KB 大小的web服务器镜像,我非常好奇,向着是否可以进一步减少我的静态站点的镜像大小。
是使用了BusyBox内置的httpd来静态文件提供web服务。于是我也学习该作者创建了一个基于busybox - httpd的web服务器镜像,将其命名为 bbhttpd,具体的构建内容请参考Github仓库 - docker-bbhttpd。
构建的镜像我也发布到Docker Hub - mengzyou/bbhttpd
$ docker image ls --format "{{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep bbhttpd
mengzyou/bbhttpd 1.35 155kB
镜像大小确实只有 155KB,是不是挺惊人的?使用该镜像来构建我的站点
...
FROM mengzyou/bbhttpd:1.35
COPY --from=builder --chown=www:www /home/hugo/app/public/ /home/www/html
docker image ls --format "{{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep myblog
myblog nginx 29MB
myblog ehttpd 19.1MB
myblog bbhttpd 5.64MB
最终的交付镜像大小只有 1.64MB,几乎也就是web服务静态文件的大小。
总结
按照Docker容器镜像构建的最佳实践,我们应该尽量保持最小的经销大小,而减少镜像大小的一个方法就是选择足够小的基础镜像。因此我们在构建静态Web服务的时候,可以通过自己构建基础镜像的方式,大大减少最终的镜像大小。
基础镜像 | nginx:1.22-alpne | mengzyou/easyhttpd:v0.0.1 | mengzyou/bbhttpd:1.35 |
---|---|---|---|
Size | 23.5MB | 13.7MB | 155KB |
同步发布在 Mengz's Blog