靜態WEB容器映象最小化實踐

夢哲發表於2022-11-22

在現代的B/S架構應用中,我們會做前後端分離,某些前端Web服務會將編譯完成的靜態檔案放到一個web伺服器進行部署。例如,我的部落格也是基於Hugo編譯的靜態檔案來進行部署的。

那在容器化部署模式下,我們需要基於一個web服務的基礎容器(映象)將靜態檔案構建成站點或者Web服務的容器映象來進行部署。在Docker開發最佳實踐中,我們應該儘量保持映象足夠小(Size大小)。因此,我們應該儘量選擇滿足我們需求的web服務基礎映象足夠小。

static-webserver-container

大部分情況下,我們會選擇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-alpnemengzyou/easyhttpd:v0.0.1mengzyou/bbhttpd:1.35
Size23.5MB13.7MB155KB
同步釋出在 Mengz's Blog

相關文章