­

docker找回構建時被刪除的文件

設想這樣一個場景:當一個docker鏡像被多次引用構建,在某次構建中某個文件被刪除,如何找回被刪除的文件?

 

要想回答這麼一個問題,首先得熟悉下docker鏡像的分層存儲結構,鏡像每一層都是只讀的:

1620

 

那當我們執行docker pull imagename 時,拉下來的鏡像每一層是存放在哪的呢?

[root@zjmaster ~]# docker info
Storage Driver: overlay2
Docker Root Dir: /var/lib/docker
從docker info輸出我們知道,此機器上docker是以overlay2作為驅動,docker相關文件的存儲目錄為/var/lib/docker

1596877797_28_w673_h360.png

此目錄還包含了鏡像,容器,網路,存儲卷等資訊。

 

由於我們用的是overlay2,所以我們的鏡像存儲的目錄是: /var/lib/docker/overlay2,在這個目錄下,我們將可以找到每個鏡像層的文件,在每個子目錄的diff目錄中可以找到當前層相對於上一層的文件變化情況。

 

如下通過一個我們熟悉的nginx鏡像來解析說明:

[root@zjmaster ~]# docker pull nginx

[root@zjmaster ~]# docker inspect nginx

“GraphDriver”: {
“Data”: {
“LowerDir”: “/var/lib/docker/overlay2/15891b392a181e5f93d8af360a5dc7cf3a0bd929e619336797d8a3ffd5b50ef0/diff:/var/lib/docker/overlay2/a5e75f89dea7bcea271c61316339a5ce8cab0df65a39f040aa36bb2ec272adad/diff:/var/lib/docker/overlay2/1759d17a2cf99e000b0500c51d3d5873df35dd8442fc111b3b642be9b43705c4/diff:/var/lib/docker/overlay2/71983445e648623b51c22994ff62c571a75c8179fc60467eb2e789cf6eba7d79/diff”,
“MergedDir”: “/var/lib/docker/overlay2/3ff91f7302cb140448b917ede7d91a7afec00871145353d3c176d1b1e16389b2/merged”,
“UpperDir”: “/var/lib/docker/overlay2/3ff91f7302cb140448b917ede7d91a7afec00871145353d3c176d1b1e16389b2/diff”,
“WorkDir”: “/var/lib/docker/overlay2/3ff91f7302cb140448b917ede7d91a7afec00871145353d3c176d1b1e16389b2/work”
},
“Name”: “overlay2”
},

 

在GraphDriver.Data中有幾個資訊:

LowerDir: Read-only image layers separated by colons from top most layer -> bottom most layer

MergedDir: Merged view of all the layers

UpperDir: Read-write layer where changes are written

WorkDir: Used specifically by the underlying Linux OverlayFS

鏡像每一層的資訊,在docker inspect image主要就關注LowerDir 和 UpperDir

可以看到,上述的nginx鏡像是由五個鏡像層組成的(LowerDir中4個+UpperDir中1個)。與docker pull時的層數是一致的:

1596877674_80_w981_h258.png

 

 

同時,我們用docker history 命令可以看到鏡像的歷史構建資訊。

1596874123_49_w1242_h427.png

在Dockerfile中,只有RUN COPY ADD命令會產生新層,其它命令只會創建臨時中間鏡像,不會增加鏡像的大小,可以看到,這裡也是有五個層,與上面的相對應。

由鏡像的分層結構存儲我們可以知道,如果有一個文件在後續的構建中被刪除,那如果我們能找到刪除時上一層的diff文件,我們是能知道被刪除的文件是怎樣的。有這麼一個題目:有一個docker 鏡像 nginx-php 正在運行,容器中的 env.php 文件在構建鏡像時被誤刪了,請想辦法找回這個文件,將它放回到容器正確的位置。

 

找回方法

第一步:

獲取鏡像歷史構建資訊,並標出層級:

1596878504_19_w1293_h400.png

 

由此我們知道env.php是在第四層被刪除的,所以我們只需要找到第三層的文件即可恢復。

 

第二步:

用docker inspect 獲取第三層的diff路徑:

[root@TENCENT64 /]# docker inspect nginx-php

“GraphDriver”: {
“Name”: “overlay2”,
“Data”: {
“LowerDir”: “/var/lib/docker/overlay2/81d273995d89ed7da9f9a6b7b68683ebf7776ac7247e0f46c815f0f736dce011/diff:/var/lib/docker/overlay2/7dd42d9227abd33d8d926b04c572aba8ee4e3cd39479935637657c47caf1bdbf/diff:/var/lib/docker/overlay2/c7febf6a82208290a35760ce1c966bd3481a88e40d64005444ece29e47656809/diff:/var/lib/docker/overlay2/85876f4cb3f2fdbb9ac1ee0c3a4ff7d50789bc705db6522ece3221d88863642c/diff:/var/lib/docker/overlay2/e37b4d0d32bdcd47832c309ce9a05ad6924468bba00e227a2aef3400cd16b825/diff”,
“MergedDir”: “/var/lib/docker/overlay2/0d0ad887405cce471cc371bfd31711c110ea7ae48318f63ff638a68dd6659e0a/merged”,
“UpperDir”: “/var/lib/docker/overlay2/0d0ad887405cce471cc371bfd31711c110ea7ae48318f63ff638a68dd6659e0a/diff”,
“WorkDir”: “/var/lib/docker/overlay2/0d0ad887405cce471cc371bfd31711c110ea7ae48318f63ff638a68dd6659e0a/work”
}
},

UpperDir 為最上層,在此為第六層,其它從LowerDir一層層往下數。

/var/lib/docker/overlay2/0d0ad887405cce471cc371bfd31711c110ea7ae48318f63ff638a68dd6659e0a/diff 第六層

/var/lib/docker/overlay2/81d273995d89ed7da9f9a6b7b68683ebf7776ac7247e0f46c815f0f736dce011/diff  第五層

/var/lib/docker/overlay2/7dd42d9227abd33d8d926b04c572aba8ee4e3cd39479935637657c47caf1bdbf/diff 第四層

/var/lib/docker/overlay2/c7febf6a82208290a35760ce1c966bd3481a88e40d64005444ece29e47656809/diff 第三層 

/var/lib/docker/overlay2/85876f4cb3f2fdbb9ac1ee0c3a4ff7d50789bc705db6522ece3221d88863642c/diff 第二層

/var/lib/docker/overlay2/e37b4d0d32bdcd47832c309ce9a05ad6924468bba00e227a2aef3400cd16b825/diff 第一層

 

進入目錄果真看到了被刪除前的文件,將文件複製出來,並放在運行中的容器即可。

1596878888_61_w1457_h605.png