今天我們來深入做點研究,
以前就發現,一項官方的 docker image,總是會有很多不同的 image 版本,
其中有什麼差異,一直都沒有仔細研究,今天就讓我們來觀察看看,Node.Js 的官方 image。
在昨天的文章中,我們建立一個自己的 docker image,
在 Docker 的世界中,所有的應用程式要改用 Docker 執行,就需要先建置成 Docker Image,
定義如何建置的檔案就叫 Dockerfile
,其中可以看到第一行總是寫了 FROM
這個關鍵字,意思是新的 Image 是要基於哪一個現有的 Docker image 來製作,又可以稱為 Base Image,
因為我們是用 JavaScript 寫,所以使用了 node
image 作為 base image。
進到 Node.Js 官方 Image 的頁面後,可以看到一整排的版本編號 (aka. image tag
),同一排的都是同一個 image,只是定義了多個別名 (tag
),
方便起見,我只探討 Long-term support (LTS) 的版本,而目前 Node.JS 本身的 LTS 版本是 16,因此我們只看 lts-xxx 的 image 版本,可以依序看到:
lts-apline3.15
lts-alpine
lts-bullseye
lts-bullseye-slim
lts
(lts-buster
)lts-slim
(lts-buster-slim
)這些 Image 同樣都可以用來執行 Node.Js 的程式,那它們到底有什麼不一樣呢?
想要深入看 image 的內容,不一定需要實際把 image 跑起來,大部分開源的 docker image 都可以找到 Dockerfile,那我們從 lts 開始,
node image 目前的 lts 被放在 lts-buster 上,buster 是什麼意思呢? 在 Google 搜尋前,我們先找找其他線索,
可以看到在 lts-buster 的 Dockerfile 中,定義它是基於一個叫 buildpack-deps:buster
的 docker image,而它又基於 buildpack-deps:buster-scm
image。
# node:lts-buster Dockerfile
FROM buildpack-deps:buster
RUN groupadd --gid 1000 node \
...
ENTRYPOINT ["docker-entrypoint.sh"]
CMD [ "node" ]
# buildpack-deps:buster Dockerfile
FROM buildpack-deps:buster-scm
RUN set -ex; \
apt-get update; \
apt-get install -y --no-install-recommends \
...
就這樣一路追查下去,會發現它的源頭是基於 debian
image,並且 debian 基於 scratch
image,
# debian:buster Dockerfile
FROM scratch
ADD rootfs.tar.xz /
CMD ["bash"]
關於 base image 的線索就到此為止,因為 scratch 不會再有 base image,為什麼呢?
原來 scratch
在 Docker 中是有特殊意義的,它並不是一個真實存在的 docker image,而是代指「空的內容」,所有 docker image 最源頭都是基於它 [1],
OK,那我們可以往回查了,下面一位:debian image,
Debian 本身是一個非常追求穩定的 Linux 發行版本,很適合作為 Server 使用,
而 debian image 就是基於 Debian 版本來製作的 docker image。
接著我們可以找到 Debian 的版本號列表,現在的 LTS 版本號 10 就叫做 buster
,下一版 11 叫做 bullseye
,
這裡就可以對應回 node 的 docker image 版本名稱了,所以 lts-buster
跟 lts-bullseye
其實就是由不同的 Debian 製作而來的,
再下一位:buildpack-deps
,看 image 的描述,似乎是幫我們裝了一些開發或執行的軟體,
It includes a large number of "development header" packages needed by various things like Ruby Gems, PyPI modules, etc.
所以說,node:lts
就是基於 Debian 10 (buster) 加上一些工具所組成的 docker image,
那麼 lts-slim
呢?
lts-slim
目前也叫 lts-buster-slim
,所以可以知道它是基於 Debian 10,根據 Dockerfile 可以接著追查到 debian:buster-slim
image,
# node:lts-buster-slim
FROM debian:buster-slim
...
# debian:buster-slim Dockerfile
FROM scratch
ADD rootfs.tar.xz /
CMD ["bash"]
所以可以知道,node image 的 lts
跟 lts-slim
之間的差異,主要在於沒有加入 buildpack-deps
的那些開發工具,lts-slim
是個相較輕量的 Node.Js image 版本。
最後輪到了 lts-alpine
image,它是一個基於 Alpine image 的版本,alpine image 本身極度輕量化,只有 5 MB,
但我就不針對 Alpine 多做介紹了,有興趣的讀者可以深入去瞭解 Alpine 的細節。
我們把這些 image 都 pull 下來看看,觀察一下大小:
$ sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node lts-buster-slim 572389d8c38d 5 days ago 179MB
node lts-slim 572389d8c38d 5 days ago 179MB
node lts e90654c39524 5 days ago 911MB
node lts-buster e90654c39524 5 days ago 911MB
node lts-bullseye-slim 8e4ba45a6265 5 days ago 191MB
node lts-bullseye e707a730fc3b 5 days ago 941MB
debian stable-slim 65114df9fe5c 5 days ago 80.5MB
debian stable 9b4953ae981c 5 days ago 124MB
node lts-alpine 5dcd1f6157bd 4 weeks ago 115MB
alpine latest 9c6f07244728 5 weeks ago 5.54MB
可以看到 node image 中,最小的是 lts-alpine
115MB,其次是 lts-slim
179MB,而 lts
本身則是大其他者非常多:911MB。
最後,
在大致瞭解它們的差異之後,那我們應該要選哪一個 node iamge 版本來使用呢?以下是我個人的主觀意見:
在大部分情況,優先使用 lts-slim
,既輕量,又可以完成大部分的事情,
如果想要或需要去追求極致的輕量化,那就使用 lts-alpine
,
其他有什麼其他理由,就依照當下情境所需跟個人喜好來選擇了,沒有一定的標準,
那我們結束今天對 docker image 的研究,明天見。