Skip to content

Commit 3c4f7e5

Browse files
committed
feat: add new article for docker
1 parent 48d4f0d commit 3c4f7e5

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
title: 透過 Docker Image 理解 OverlayFS
3+
date: 2024-11-19 13:33:00
4+
---
5+
6+
在日常的開發或是部署當中,我們很常使用 Docker 來免去環境設定還有跨平台的困擾,那你有沒有好奇過:如果我們的電腦裡面有很多 Docker Image,會不會佔用很多電腦的硬碟空間嗎?Docker 是如何儲存這些 Image 的?
7+
8+
## :whale: Dockerfile 與 Image Layer 實現原理
9+
10+
日常開發中,經常會看到這樣的 Dockerfile:
11+
12+
```dockerfile
13+
FROM ubuntu:20.04
14+
RUN apt-get update && apt-get install -y nginx
15+
COPY ./app /app
16+
CMD ["nginx", "-g", "daemon off;"]
17+
```
18+
19+
當我們執行 `docker build` 的時候,每個指令都會產生一個新的 layer:
20+
21+
```bash
22+
[+] Building 33.8s (8/8) FINISHED
23+
=> [internal] load build definition from Dockerfile
24+
=> => transferring dockerfile: 172B
25+
=> [internal] load metadata for docker.io/library/ubuntu:20.04
26+
=> [1/3] FROM docker.io/library/ubuntu:20.04
27+
=> [2/3] RUN apt-get update && apt-get install -y nginx
28+
=> [3/3] COPY ./app /var/www/html
29+
=> exporting to image
30+
=> => writing image sha256:5d8f96da221d162a0937f2241bd9236e7dfc90872cda77498c467369fc885b6
31+
```
32+
33+
可以使用 `docker history` 來查看這些 layer 的組成:
34+
35+
```bash
36+
IMAGE CREATED CREATED BY SIZE COMMENT
37+
5d8f96da221d 47 seconds ago CMD ["nginx" "-g" "daemon off;"] 0B buildkit.dockerfile.v0
38+
<missing> 47 seconds ago COPY ./app /var/www/html # buildkit 27B buildkit.dockerfile.v0
39+
<missing> 47 seconds ago RUN /bin/sh -c apt-get update && apt-get... 114MB buildkit.dockerfile.v0
40+
<missing> 5 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
41+
<missing> 5 weeks ago /bin/sh -c #(nop) ADD file:74861... 72.8MB
42+
```
43+
44+
你有沒有好奇過,為什麼每個指令都會產生一個新的層?這些層是如何組合在一起的?更重要的是,為什麼我們在容器裡修改檔案時,不會影響到原本的映像檔?
45+
每個 Docker Image 都是由多個層堆疊而成的。以上面的例子來說:
46+
47+
- 最底層是 Ubuntu 20.04 的基礎映像檔(72.8MB),包含了基本的作業系統檔案
48+
- 接著是執行 apt-get install nginx 產生的層(114MB),包含了 nginx 相關的檔案
49+
- 然後是 COPY 指令產生的層(27B),包含了我們的應用程式檔案
50+
- 最後是 CMD 指令產生的層(0B),只包含了啟動指令的設定
51+
52+
這種分層設計帶來了很多好處:
53+
54+
- 空間利用率:多個容器可以共享相同的基礎層。想像一下,如果有 10 個專案都是基於 Ubuntu 20.04,這些專案的容器就可以共用同一個基礎映像層,而不是每個專案都儲存一份完整的作業系統檔案。
55+
- 建構效率:Docker 會快取每一層。如果只是修改了應用程式的程式碼,重新建構時只需要從 COPY 指令開始,前面的層都可以直接複用。這大幅減少了開發過程中的等待時間。
56+
57+
當我們執行 `docker run` 啟動容器時,Docker 會在最上層添加一個可寫入的容器層。這就是為什麼我們可以在容器內新增或修改檔案,但這些變更不會影響到原本的映像檔。讓我們實際試試:
58+
59+
```bash
60+
docker run -it ubuntu:20.04 bash
61+
root@container:/# touch newfile
62+
root@container:/# echo "hello" > /etc/motd
63+
```
64+
65+
這些修改只會寫入到容器層,而且當容器被刪除時,這些變更也會跟著消失。如果你希望保存這些變更,就需要使用 `docker commit` 將容器的當前狀態儲存為新的映像檔。
66+
67+
但這樣的分層機制是如何實現的呢?這就要談到 Linux 核心中的 OverlayFS 了。它不只是一個簡單的檔案系統,而是專門設計用來處理多層檔案系統疊加的解決方案。
68+
69+
## :whale: 從 UnionFS 到 OverlayFS 的演進
70+
71+
## :whale: OverlayFS 核心機制實作解析
72+
73+
## :whale: OverlayFS 在實務上的其他應用
74+
75+
## :whale: Resource
76+
77+
- [OverlayFS storage driver | Docker Docs](https://docs.docker.com/engine/storage/drivers/overlayfs-driver/)
78+
- [Overlay Filesystem — The Linux Kernel documentation](https://docs.kernel.org/filesystems/overlayfs.html)
79+
- [Overlay filesystem - ArchWiki](https://wiki.archlinux.org/title/Overlay_filesystem)
80+
- [OverlayFS and its use in Yocto Project - Vyacheslav Yurkov, Precitec GmbH & Co. KG](https://www.youtube.com/watch?v=03sOH9GaKO4)

0 commit comments

Comments
 (0)