0%

docker 系列 - (4) Dockerfile容器的儲存

1. 容器儲存介紹

預設情況下,在運行中的容器裡創建的文件,被保存在一個可寫的容器層:

  • 如果容器被刪除了,則數據也沒有了
  • 這個可寫的容器層是和特定的容器綁定的,也就是這些數據無法方便的和其它容器共享

Docker主要提供了三種方式做數據的持久化

  • Data Volume

    • 由Docker管理,(/var/lib/docker/volumes/linux),持久化數據的最好方式
  • Bind Mount

    • 由用戶指定存儲的數據具體mount在系統什麼位置
  • tmpfs Mount

    • 這個比較少用到,暫時先不進行介紹

docker-volume

2. Data Volume

我們來探討如何進行數據的持久化。

  • “一個運行中的docker image”
  • 實質是複製image全在image最上層加上一層read-write的層(稱之為container layer,容器層)
  • 基於同一個IMAGE可以創建多個container

img

2.1. 環境準備

準備一個Dockerfile和一個my-cron的文件

dockerfile-cron

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM alpine:latest
RUN apk update
RUN apk --no-cache add curl
ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \
SUPERCRONIC=supercronic-linux-amd64 \
SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e
RUN curl -fsSLO "$SUPERCRONIC_URL" \
&& echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \
&& chmod +x "$SUPERCRONIC" \
&& mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
&& ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic
COPY my-cron /app/my-cron
WORKDIR /app

#volume 可以定義多個,這邊只定義一個
VOLUME ["/app"]

# RUN cron job
CMD ["/usr/local/bin/supercronic", "/app/my-cron"]

my-cron

1
*/1 * * * * date >> /app/test.txt

資料夾結構

1
2
3
.
├── dockerfile-cron
├── my-cron

2.2. 基本使用volume

2.2.1. 搭建環境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#建立dockefile-cron檔案,請自行完成腳本內容
kite@kite-virtual-machine:~/Desktop/genDockerImagesFolder$ touch dockerfile-cron

#建立my-cron檔案,請自行完成腳本內容
kite@kite-virtual-machine:~/Desktop/genDockerImagesFolder$ touch my-cron

#建立鏡像檔
kite@kite-virtual-machine:~/Desktop/genDockerImagesFolder$ sudo docker image build -f dockerfile-cron -t my-cron .
Sending build context to Docker daemon 892.4kB
Step 1/9 : FROM alpine:latest
...
...
Successfully built a5105bc596ec
Successfully tagged my-cron:latest

#查看鏡像檔清單
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-cron latest a6e1e40dd6bb 15 minutes ago 45MB

#啟動並創建容器
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker run -d my-cron
97d956e771f6a833368d6ecc693aa79fb300eb04cfc0b435bc665652013401ec

#查看容器清單
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker container ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
97d956e771f6 my-cron "/usr/local/bin/supe…" 5 seconds ago Up 4 seconds tender_mahavira

2.2.2. 確認crontab執行狀況

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#進入容器
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker exec -it 97d9 sh

#查詢檔案
/app # ls
my-cron test.txt

#查看test.txt檔案
/app # more test.txt
Wed Feb 23 02:11:00 UTC 2022
Wed Feb 23 02:12:00 UTC 2022

#離開容器
/app # exit

2.2.3. 查看host檔案路徑(Mountpoint)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#查看volume 清單
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker volume ls
DRIVER VOLUME NAME
local 05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5

#查看volume映射資料
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker volume inspect 05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5
[
{
"CreatedAt": "2022-02-23T10:10:59+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5/_data",
"Name": "05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5",
"Options": null,
"Scope": "local"
}
]

#使用ls 加 mountpoint值的路徑,可以發現在host上也有test.txt檔案
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# ls /var/lib/docker/volumes/05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5/_data
my-cron test.txt

#使用more查看host的test.txt檔案,資料與容器內部一致
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# more /var/lib/docker/volumes/05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5/_data/test.txt
Wed Feb 23 02:11:00 UTC 2022
Wed Feb 23 02:12:00 UTC 2022

2.2.4. 驗證停止container後,host檔案是否仍存在

1
2
3
4
5
6
7
#停止容器
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker container stop 97d

#驗證,就算停止容器host檔案還是存在的
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# more /var/lib/docker/volumes/05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5/_data/test.txt
Wed Feb 23 02:11:00 UTC 2022
Wed Feb 23 02:12:00 UTC 2022

2.2.5. 發現再啟用新的容器,volume重建一個新的區域

1
2
3
4
5
6
7
8
9
#再啟動一個新的container
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker container run -d my-cron
17f1ffa9999a697540fb4aa81a695b66d96b9f57ac05db6af8f9026da4bdb6a7

#查看volume清單,會發現多了一個b49bbb,代表這個容器使用了一個新的硬碟空間
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker volume ls
DRIVER VOLUME NAME
local 05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5
local b49bbb9e19dedb0bb36dc3b734ec354eb25e477212dbb5a5156416c63693a25d

2.2.6. 如何接續上一個volume資料?

如果container停止後,再繼續啟用一個新的container,我們想要接續上一個container的資料繼續記錄。如何做到呢?

首先,我們把之前實驗的資料進行清空的動作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#查看目前所有container包含停止的container
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker container ps -a
CONTAINER ID IMAGE COMMAND ...
17f1ffa9999a my-cron "/usr/local/bin/supe…" ...
97d956e771f6 my-cron "/usr/local/bin/supe…" ...

#強制停止container
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker container rm -f 17f1 97d9

#刪除所有volume,會詢問是否繼續
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker volume prune
WARNING! This will remove all local volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
05b3074b5770b1a24b36493a3b1153a1070206d4600d19a1508714c9912dc5f5
b49bbb9e19dedb0bb36dc3b734ec354eb25e477212dbb5a5156416c63693a25d

Total reclaimed space: 1.402kB

#查看volume 都清空了
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker volume ls
DRIVER VOLUME NAME

此項任務**-v 我是主角**:

1
docker container run -d -v [自定義volume名稱]:[dockerfile內必須有的設定值] [image name]

執行過程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#使用 -v 參數,也就是代表volume的意思 cron-data volume 名稱,而冒號(:) 後面的 /app 必須是在dockerfile有指名的volume
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker container run -d -v cron-data:/app my-cron
6150f7169a578f27af13997ec8d8f9ca2610fa4c7aae0b97a57bef5bf9d845d6

#查看一下volume 就會看到以cron-data為名稱的volume
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker volume ls
DRIVER VOLUME NAME
local cron-data

#查看volume資料,mountpoint路徑就變簡潔了
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker volume inspect cron-data
[
{
"CreatedAt": "2022-02-23T11:24:59+08:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/cron-data/_data",
"Name": "cron-data",
"Options": null,
"Scope": "local"
}
]

進行驗證,是否有接續之前的資料

我們會發現進入container後看test.txt文件內容,是有包含之前上一次container 的資料在裡面哦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#先刪除之前的container
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker container rm -f 6150
6150

#再次創建container
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker container run -d -v cron-data:/app my-cron
f61223479947f23bb6750d25aa22427e3b8dbb92875af9d4c3dbac761703ea29

#進入container
root@kite-virtual-machine:/home/kite/Desktop/pythonworkspace# docker exec -it f6122 sh
/app # ls
my-cron test.txt
/app # more test.txt
Wed Feb 23 03:25:00 UTC 2022
Wed Feb 23 03:26:00 UTC 2022
Wed Feb 23 03:27:00 UTC 2022
Wed Feb 23 03:28:00 UTC 2022
Wed Feb 23 03:29:00 UTC 2022
Wed Feb 23 03:30:00 UTC 2022
/app # exit

註記:

1
2
3
4
#刪除所有鏡像
docker system prune

docker volume rm $(docker volume ls -qf dangling=true)

網站推薦

crontab轉換

3. 數據持久化之Bind Mount

複習一下在dockerfile裡面定義了VOLUME,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
FROM alpine:latest
RUN apk update
RUN apk --no-cache add curl
ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.1.12/supercronic-linux-amd64 \
SUPERCRONIC=supercronic-linux-amd64 \
SUPERCRONIC_SHA1SUM=048b95b48b708983effb2e5c935a1ef8483d9e3e
RUN curl -fsSLO "$SUPERCRONIC_URL" \
&& echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \
&& chmod +x "$SUPERCRONIC" \
&& mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
&& ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic
COPY my-cron /app/my-cron
WORKDIR /app

#volume 可以定義多個,這邊只定義一個
VOLUME ["/app"]

# RUN cron job
CMD ["/usr/local/bin/supercronic", "/app/my-cron"]

如果希望都是以參數方式定義VOLUME的話,在dockerfile的部分就可以不用去寫這段語法。

另外,windows 在使用volume時會有一些狀況。還記得windows的docker環境,其實是run在linux虛擬層裡。所以在使用docker volume inspect指令查閱Mountpoint的路徑是一個linux的路徑。但是在windows作業系統是摸不到這一層的。

因此,在windows環境使用Bind Mount方式好用一些。試著在windows運行,延用先前的dockerfile-cron檔案及my-cron腳本,玩玩看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#查看目前的images
PS E:\dockerworkspace> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-cron latest f356932e5078 22 seconds ago 24.8MB

#創建並運行容器,${pwd} 指的是當前目錄
PS E:\dockerworkspace> docker container run -d -v ${pwd}:/app my-cron

#我們會看到在windows底下,排程時間到了就自動產生test.txt檔案
PS E:\dockerworkspace> tree /f /a
列出磁碟區 Data 的資料夾 PATH
磁碟區序號為 3A21-AA41
E:.
Dockerfile
my-cron
test.txt

#輸出檔案內容
PS E:\dockerworkspace> type test.txt
Wed Feb 23 08:38:00 UTC 2022
Wed Feb 23 08:39:00 UTC 2022

4. Bind Mount練習之docker開發環境

host沒有編譯環境,希望透過container來 bind相同的資料區塊,用這個方式的確很輕鬆產生編譯後的檔案。

當前目錄指令說明

  • linux
    • $(pwd)
  • windows
    • ${pwd}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#查看目前目錄檔案,目前只有一個hello.c
root@kite-virtual-machine:/home/kite/Desktop/bindMountArea# ls
hello.c

#創建並運行container $(pwd) 指的是當前目錄
root@kite-virtual-machine:/home/kite/Desktop/bindMountArea# docker container run -it -v $(pwd):/app gcc:9.4

#已進入容器,查看列表
root@e058f803400b:/# ls
app bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

root@e058f803400b:/# cd app

#查看的確在/app資料夾底下有跟host一樣的hello.c檔案
root@e058f803400b:/app# ls
hello.c

#進行編譯
root@e058f803400b:/app# gcc -o hello hello.c

#編完譯後多出一個hello檔
root@e058f803400b:/app# ls
hello hello.c

#小玩一下
root@e058f803400b:/app# ./hello abc
hello abc

root@e058f803400b:/app# ./hello kite
hello kite


#退出容器
root@e058f803400b:/app# exit

#在host的確也有hello檔案
root@kite-virtual-machine:/home/kite/Desktop/bindMountArea# ls
hello hello.c

5. 機器之間共享數據

待補