在現代的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