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文件,我們是能知道被刪除的文件是怎樣的。我們來構建一個這樣的場景並演示如何恢復。

 

 

第一步,拉取一個ubuntu:18.04基礎鏡像。

[root@zjmaster /]# docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
7595c8c21622: Pull complete
d13af8ca898f: Pull complete
70799171ddba: Pull complete
b6c12202c5ef: Pull complete
Digest: sha256:a61728f6128fb4a7a20efaa7597607ed6e69973ee9b9123e3b4fd28b7bba100b
Status: Downloaded newer image for ubuntu:18.04
[root@zjmaster /]# docker history ubuntu:18.04
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
2eb2d388e1a2        2 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           2 weeks ago         /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B
<missing>           2 weeks ago         /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   745B
<missing>           2 weeks ago         /bin/sh -c [ -z "$(apt-get indextargets)" ]     987kB
<missing>           2 weeks ago         /bin/sh -c #(nop) ADD file:7d9bbf45a5b2510d4…   63.2M

 

 

 

 

第二步:制作Dockerfile,刪除copy進去的screct.txt文件,並運行容器

[root@zjmaster /data/docker]# cat Dockerfile
FROM ubuntu:18.04

COPY secret.txt /tmp/secret.txt
RUN rm /tmp/secret.txt

EXPOSE 80
CMD ["/bin/bash"]
[root@zjmaster
/data/docker]# cat secret.txt Hello World! [root@zjmaster /data/docker]# docker build -t ubuntu:rmfile . Sending build context to Docker daemon 3.072kB Step 1/5 : FROM ubuntu:18.04 ---> 2eb2d388e1a2 Step 2/5 : COPY secret.txt /tmp/secret.txt ---> 2856d2f8f07f Step 3/5 : RUN rm /tmp/secret.txt ---> Running in de4ed8d2790b Removing intermediate container de4ed8d2790b ---> 313f23ffc4fc Step 4/5 : EXPOSE 80 ---> Running in fcc0ba3961f5 Removing intermediate container fcc0ba3961f5 ---> ede9fff02d30 Step 5/5 : CMD ["/bin/bash"] ---> Running in 01986f45d0c2 Removing intermediate container 01986f45d0c2 ---> 26ffd7e8f2ef Successfully built 26ffd7e8f2ef Successfully tagged ubuntu:rmfile [root@zjmaster /data/docker]# docker run -idt ubuntu:rmfile /bin/bash 49c74ce8afee493107daf1415bb01406978c109c2927cdd92d1881fd5dbe2f66 [root@zjmaster /data/docker]# [root@zjmaster /data/docker]# docker exec 49c74ce8afee493107daf1415bb01406978c109c2927cdd92d1881fd5dbe2f66 /bin/bash -c 'ls /tmp/secret.txt' ls: cannot access '/tmp/secret.txt': No such file or directory
可以發現容器中的/tmp目前並沒有secret.txt文件。接下來我們嘗試找回這個文件。


第三步:

獲取鏡像歷史構建信息,並標出層級:

[root@zjmaster /data/docker]# docker history ubuntu:rmfile
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
26ffd7e8f2ef        2 minutes ago       /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
ede9fff02d30        2 minutes ago       /bin/sh -c #(nop)  EXPOSE 80                    0B
313f23ffc4fc        2 minutes ago       /bin/sh -c rm /tmp/secret.txt                   0B       第六層
2856d2f8f07f        2 minutes ago       /bin/sh -c #(nop) COPY file:bd6fdd1577f2abf2…   13B      第五層
2eb2d388e1a2        2 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
<missing>           2 weeks ago         /bin/sh -c mkdir -p /run/systemd && echo 'do…   7B       第四層
<missing>           2 weeks ago         /bin/sh -c set -xe   && echo '#!/bin/sh' > /…   745B     第三層
<missing>           2 weeks ago         /bin/sh -c [ -z "$(apt-get indextargets)" ]     987kB    第二層
<missing>           2 weeks ago         /bin/sh -c #(nop) ADD file:7d9bbf45a5b2510d4…   63.2MB   第一層

 

 

由此我們知道secret.txt是在第六層被刪除的,所以我們只需要找到第五層的文件即可恢復。

 

第四步:

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

[root@zjmaster /data/docker]# docker inspect ubuntu:rmfile

"GraphDriver": {

"Data": {
"LowerDir": "/var/lib/docker/overlay2/a51164d454343a309fec1fc9e34511ccb15c42107ecfddd75b5e3f3536c0ab9f/diff:/var/lib/docker/overlay2/0aa0f1c5a06d463c495c61e9d15fe6ad87b80c34b80450651f0e43f4ef0b1629/diff:/var/lib/docker/overlay2/86ed072ad089a17e0b14f0658d85c91eab9ff1e6cdca36f54e24d066ab8db019/diff:/var/lib/docker/overlay2/b03c3e40173d1fa67806c674d7ace749b1a1fba65939b9f841df44ada1c428eb/diff:/var/lib/docker/overlay2/3b1ae2f59bdc2fe8260f04d9e4b7ba61eff75bff190673c4c8e856a86e998b7e/diff",
"MergedDir": "/var/lib/docker/overlay2/37dc44c3887436e3fd446a0b8b137d7093a357ee42f6c83f03622c6d446757f4/merged",
"UpperDir": "/var/lib/docker/overlay2/37dc44c3887436e3fd446a0b8b137d7093a357ee42f6c83f03622c6d446757f4/diff",
"WorkDir": "/var/lib/docker/overlay2/37dc44c3887436e3fd446a0b8b137d7093a357ee42f6c83f03622c6d446757f4/work"
},
"Name": "overlay2"
},

 

 

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

/var/lib/docker/overlay2/37dc44c3887436e3fd446a0b8b137d7093a357ee42f6c83f03622c6d446757f4/diff 第六層
/var/lib/docker/overlay2/a51164d454343a309fec1fc9e34511ccb15c42107ecfddd75b5e3f3536c0ab9f/diff 第五層 /var/lib/docker/overlay2/0aa0f1c5a06d463c495c61e9d15fe6ad87b80c34b80450651f0e43f4ef0b1629/diff 第四層
/var/lib/docker/overlay2/86ed072ad089a17e0b14f0658d85c91eab9ff1e6cdca36f54e24d066ab8db019/diff 第三層
/var/lib/docker/overlay2/b03c3e40173d1fa67806c674d7ace749b1a1fba65939b9f841df44ada1c428eb/diff 第二層
/var/lib/docker/overlay2/3b1ae2f59bdc2fe8260f04d9e4b7ba61eff75bff190673c4c8e856a86e998b7e/diff 第一層

 

進入第五層目錄果真看到了被刪除前的文件。

[root@zjmaster /]# tree /var/lib/docker/overlay2/a51164d454343a309fec1fc9e34511ccb15c42107ecfddd75b5e3f3536c0ab9f/diff
/var/lib/docker/overlay2/a51164d454343a309fec1fc9e34511ccb15c42107ecfddd75b5e3f3536c0ab9f/diff
`-- tmp
    `-- secret.txt

1 directory, 1 file
[root@zjmaster /]# cat /var/lib/docker/overlay2/a51164d454343a309fec1fc9e34511ccb15c42107ecfddd75b5e3f3536c0ab9f/diff/tmp/secret.txt
Hello World!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM