-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
48d4f0d
commit 3c4f7e5
Showing
1 changed file
with
80 additions
and
0 deletions.
There are no files selected for viewing
80 changes: 80 additions & 0 deletions
80
docs/notes/Docker/understand-overlayFS-through-docker-image-layers.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
--- | ||
title: 透過 Docker Image 理解 OverlayFS | ||
date: 2024-11-19 13:33:00 | ||
--- | ||
|
||
在日常的開發或是部署當中,我們很常使用 Docker 來免去環境設定還有跨平台的困擾,那你有沒有好奇過:如果我們的電腦裡面有很多 Docker Image,會不會佔用很多電腦的硬碟空間嗎?Docker 是如何儲存這些 Image 的? | ||
|
||
## :whale: Dockerfile 與 Image Layer 實現原理 | ||
|
||
日常開發中,經常會看到這樣的 Dockerfile: | ||
|
||
```dockerfile | ||
FROM ubuntu:20.04 | ||
RUN apt-get update && apt-get install -y nginx | ||
COPY ./app /app | ||
CMD ["nginx", "-g", "daemon off;"] | ||
``` | ||
|
||
當我們執行 `docker build` 的時候,每個指令都會產生一個新的 layer: | ||
|
||
```bash | ||
[+] Building 33.8s (8/8) FINISHED | ||
=> [internal] load build definition from Dockerfile | ||
=> => transferring dockerfile: 172B | ||
=> [internal] load metadata for docker.io/library/ubuntu:20.04 | ||
=> [1/3] FROM docker.io/library/ubuntu:20.04 | ||
=> [2/3] RUN apt-get update && apt-get install -y nginx | ||
=> [3/3] COPY ./app /var/www/html | ||
=> exporting to image | ||
=> => writing image sha256:5d8f96da221d162a0937f2241bd9236e7dfc90872cda77498c467369fc885b6 | ||
``` | ||
|
||
可以使用 `docker history` 來查看這些 layer 的組成: | ||
|
||
```bash | ||
IMAGE CREATED CREATED BY SIZE COMMENT | ||
5d8f96da221d 47 seconds ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0 | ||
<missing> 47 seconds ago COPY ./app /var/www/html # buildkit 27B buildkit.dockerfile.v0 | ||
<missing> 47 seconds ago RUN /bin/sh -c apt-get update && apt-get... 114MB buildkit.dockerfile.v0 | ||
<missing> 5 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B | ||
<missing> 5 weeks ago /bin/sh -c #(nop) ADD file:74861... 72.8MB | ||
``` | ||
|
||
你有沒有好奇過,為什麼每個指令都會產生一個新的層?這些層是如何組合在一起的?更重要的是,為什麼我們在容器裡修改檔案時,不會影響到原本的映像檔? | ||
每個 Docker Image 都是由多個層堆疊而成的。以上面的例子來說: | ||
|
||
- 最底層是 Ubuntu 20.04 的基礎映像檔(72.8MB),包含了基本的作業系統檔案 | ||
- 接著是執行 apt-get install nginx 產生的層(114MB),包含了 nginx 相關的檔案 | ||
- 然後是 COPY 指令產生的層(27B),包含了我們的應用程式檔案 | ||
- 最後是 CMD 指令產生的層(0B),只包含了啟動指令的設定 | ||
|
||
這種分層設計帶來了很多好處: | ||
|
||
- 空間利用率:多個容器可以共享相同的基礎層。想像一下,如果有 10 個專案都是基於 Ubuntu 20.04,這些專案的容器就可以共用同一個基礎映像層,而不是每個專案都儲存一份完整的作業系統檔案。 | ||
- 建構效率:Docker 會快取每一層。如果只是修改了應用程式的程式碼,重新建構時只需要從 COPY 指令開始,前面的層都可以直接複用。這大幅減少了開發過程中的等待時間。 | ||
|
||
當我們執行 `docker run` 啟動容器時,Docker 會在最上層添加一個可寫入的容器層。這就是為什麼我們可以在容器內新增或修改檔案,但這些變更不會影響到原本的映像檔。讓我們實際試試: | ||
|
||
```bash | ||
docker run -it ubuntu:20.04 bash | ||
root@container:/# touch newfile | ||
root@container:/# echo "hello" > /etc/motd | ||
``` | ||
|
||
這些修改只會寫入到容器層,而且當容器被刪除時,這些變更也會跟著消失。如果你希望保存這些變更,就需要使用 `docker commit` 將容器的當前狀態儲存為新的映像檔。 | ||
|
||
但這樣的分層機制是如何實現的呢?這就要談到 Linux 核心中的 OverlayFS 了。它不只是一個簡單的檔案系統,而是專門設計用來處理多層檔案系統疊加的解決方案。 | ||
|
||
## :whale: 從 UnionFS 到 OverlayFS 的演進 | ||
|
||
## :whale: OverlayFS 核心機制實作解析 | ||
|
||
## :whale: OverlayFS 在實務上的其他應用 | ||
|
||
## :whale: Resource | ||
|
||
- [OverlayFS storage driver | Docker Docs](https://docs.docker.com/engine/storage/drivers/overlayfs-driver/) | ||
- [Overlay Filesystem — The Linux Kernel documentation](https://docs.kernel.org/filesystems/overlayfs.html) | ||
- [Overlay filesystem - ArchWiki](https://wiki.archlinux.org/title/Overlay_filesystem) | ||
- [OverlayFS and its use in Yocto Project - Vyacheslav Yurkov, Precitec GmbH & Co. KG](https://www.youtube.com/watch?v=03sOH9GaKO4) |