Docker容器原理詳解

【1】Docker容器數據卷

先來看看Docker的理念:

  • 將運用與運行的環境打包形成容器運行 ,運行可以伴隨着容器,但是我們對數據的要求希望是持久化的
  • 容器之間希望有可能共享數據

Docker容器產生的數據,如果不通過docker commit生成新的鏡像,使得數據做爲鏡像的一部分保存下來,那麼當容器刪除後,數據自然也就沒有了。

爲了能保存數據在docker中我們使用數據卷,主要爲了容器的持久化與容器間繼承+共享數據(主機和容器數據共享)。

卷就是目錄或文件,存在於一個或多個容器中,由docker掛載到容器,但不屬於聯合文件系統,因此能夠繞過Union File System提供一些用於持續存儲或共享數據的特性。

卷的設計目的就是數據的持久化,完全獨立於容器的生存週期,因此Docker不會在容器刪除時刪除其掛載的數據卷。

特點:

1:數據卷可在容器之間共享或重用數據
2:卷中的更改可以直接生效
3:數據卷中的更改不會包含在鏡像的更新中
4:數據卷的生命週期一直持續到沒有容器使用它爲止

【2】命令添加數據卷

在容器內添加數據卷主要有兩種方式:直接V命令添加和DockerFile添加。

① 命令添加數據卷實例

命令如下:

 docker run -it -v /宿主機絕對路徑目錄:/容器內目錄      鏡像名
 
 #如docker run -it -v /宿主機目錄:/容器內目錄 centos /bin/bash
 docker run -it -v /myDataVolume:/dataVolumeContainer centos /bin/bash

在這裏插入圖片描述


② 查看數據卷是否掛載成功

docker inspect 容器ID

在這裏插入圖片描述

③ 容器和宿主機之間數據共享

如下所示在容器內/dataVolumeContainer目錄創建文件:

容器內操作如下:

[root@a35e55bafcab dataVolumeContainer]# echo "i'm a container " > test.txt
[root@a35e55bafcab dataVolumeContainer]# ls
test.txt
[root@a35e55bafcab dataVolumeContainer]# cat test.txt
i'm a container
[root@a35e55bafcab dataVolumeContainer]#

宿主機操作如下:

[root@localhost ~]# cd /myDataVolume/
[root@localhost myDataVolume]# ll
total 4
-rw-r--r--. 1 root root 17 Feb 12 11:46 test.txt
[root@localhost myDataVolume]# cat test.txt
i'm a container
[root@localhost myDataVolume]# echo "host update" >> test.txt
[root@localhost myDataVolume]# cat test.txt
i'm a container
host update

在這裏插入圖片描述


④ 容器停止退出後,主機修改後數據同步

驗證步驟:

  • 容器先停止退出
  • 主機修改test.txt
  • 容器重啓進入
  • 查看主機修改的test.txt

主機操作:

[root@localhost myDataVolume]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@localhost myDataVolume]# echo "host update again" >> test.txt
[root@localhost myDataVolume]# cat test.txt
i'm a container
host update
host update again

容器操作:

[root@localhost /]# docker start a35e55bafcab
a35e55bafcab
[root@localhost /]# docker exec -it a35e55bafcab  /bin/bash
[root@a35e55bafcab /]# cd /dataVolumeContainer/
[root@a35e55bafcab dataVolumeContainer]# cat test.txt
i'm a container
host update
host update again //這裏標明容器看到了主機修改的內容

⑤ 設置目錄權限

##ro表示read only 即容器內的數據只允許讀
docker run -it -v /宿主機絕對路徑目錄:/容器內目錄:ro 鏡像名

【3】DockerFile添加數據卷

這裏以一個實例來說明。

① 根目錄下新建mydocker文件夾並進入

mkdir /mydocker
cd /mydocker

② 在Dockerfile中使用VOLUME指令來給鏡像添加一個或多個數據卷

格式如下:

VOLUME["/dataVolumeContainer","/dataVolumeContainer2","/dataVolumeContainer3"]

出於可移植和分享的考慮,用-v 主機目錄:容器目錄這種方法不能夠直接在Dockerfile中實現。由於宿主機目錄是依賴於特定宿主機的,並不能夠保證在所有的宿主機上都存在這樣的特定目錄。

構建File:

[root@localhost /]# cd /mydocker/
[root@localhost mydocker]# ll
total 0
[root@localhost mydocker]# vim DockerFile

文件內容如下:

# volume test
FROM centos
VOLUME ["/dataVolumeContainer1","/dataVolumeContainer2"]
CMD echo "finished,--------success1"
CMD /bin/bash

在這裏插入圖片描述
③ build後生成鏡像

命令如下:

docker build -f DockFile路徑 -t 鏡像名 .[這裏有個.不可少,標明在當前目錄下面]

實例如下(注意當前在/mydocker路徑下,命令最後面有個.):

docker build  -f /mydocker/DockerFile -t jane/centos  .

在這裏插入圖片描述
使用docker images檢測如下:
在這裏插入圖片描述


④ 創建新的容器並運行

docker run -it b3a32e0a2930 /bin/bash

在這裏插入圖片描述

⑤ 查看容器目錄對應的主機目錄

首先檢測運行的容器:

docker ps

在這裏插入圖片描述
使用命令查看容器內部情況:

docker inspect 9ae9239b6cf7
 "Volumes": {
        "/dataVolumeContainer1": "/var/lib/docker/volumes/8ebcee3e258a367b2869c326bc7c032b544e061830490ce866ef6a72299a6999/_data",
        "/dataVolumeContainer2": "/var/lib/docker/volumes/396815bd66ac143ed2bff3f2ad8ac6439116d5fbbae53327c52b883eb6ec6d6a/_data"
    },
    "VolumesRW": {
        "/dataVolumeContainer1": true,
        "/dataVolumeContainer2": true
    }

在這裏插入圖片描述

使用命令在容器內創建文件,然後在宿主機對應目錄查看:在這裏插入圖片描述


【4】數據卷容器

命名的容器掛載數據卷,其它容器通過掛載這個(父容器)實現數據共享,掛載數據卷的容器,稱之爲數據卷容器。

① 查看此時鏡像與容器概況

在這裏插入圖片描述
② 先啓動一個父容器dc01

docker run -it --name dc01 jane/centos

檢測如下:

在這裏插入圖片描述
在dataVolumeContainer2/路徑下創建文件dc01.txt:

[root@41ad254d8e05 /]# cd dataVolumeContainer2/
[root@41ad254d8e05 dataVolumeContainer2]# touch dc01.txt
[root@41ad254d8e05 dataVolumeContainer2]# ls
dc01.txt

③ 創建容器dc02、dc03並繼承自dc01

docker run -it --name dc02 --volumes-from dc01 jane/centos

然後同樣在dataVolumeContainer2路徑下創建文件:

[root@a5f21105d3e7 /]# cd dataVolumeContainer2/
[root@a5f21105d3e7 dataVolumeContainer2]# ls
dc01.txt
[root@a5f21105d3e7 dataVolumeContainer2]# touch dc02.txt
[root@a5f21105d3e7 dataVolumeContainer2]# ls
dc01.txt  dc02.txt

dc03操作如下:

[root@localhost myDataVolume]# docker run -it --name dc03 --volumes-from dc01 jane/centos
[root@132abc66899c /]# cd dataVolumeContainer2/
[root@132abc66899c dataVolumeContainer2]# ls
dc01.txt  dc02.txt
[root@132abc66899c dataVolumeContainer2]# touch dc03.txt
[root@132abc66899c dataVolumeContainer2]# ls
dc01.txt  dc02.txt  dc03.txt

④ 返回查看容器dc01

檢測此時容器運行概況:

在這裏插入圖片描述

檢測容器dc01路徑dataVolumeContainer2概況:
在這裏插入圖片描述


⑤ 刪除dc01然後分別在dc02/dc03下查看dataVolumeContainer2路徑

在這裏插入圖片描述

#進入dc02
docker exec -it a5f21105d3e7  /bin/bash
#進入dc03
docker exec -it 132abc66899c  /bin/bash

在這裏插入圖片描述
⑥ dc02新增數據然後刪除dc02再進入dc03查看

dc02下操作:

[root@a5f21105d3e7 /]# cd dataVolumeContainer2
[root@a5f21105d3e7 dataVolumeContainer2]# ls
dc01.txt  dc02.txt  dc03.txt
[root@a5f21105d3e7 dataVolumeContainer2]# touch dc02_update.txt
[root@a5f21105d3e7 dataVolumeContainer2]# ls
dc01.txt  dc02.txt  dc02_update.txt  dc03.txt
[root@a5f21105d3e7 dataVolumeContainer2]# [root@localhost ~]#
[root@localhost ~]# docker rm -f a5f21105d3e7
a5f21105d3e7

dc03下操作:

[root@localhost ~]# docker exec -it 132abc66899c  /bin/bash
[root@132abc66899c /]# cd dataVolumeContainer2
[root@132abc66899c dataVolumeContainer2]# ls
dc01.txt  dc02.txt  dc02_update.txt  dc03.txt

可以發現儘管dc02與dc03無繼承關係,但是已經建立了共享關係,故而dc02刪除後,dc03仍然可以拿到dc02創建的文件。

結論:容器之間配置信息的傳遞,數據卷的生命週期一直持續到沒有容器使用它爲止。

問題:

  • 如果兩個獨立的容器映射了同一個主機目錄會怎樣?
  • 如果dc01 dc02 dc03三個沒有關係還會出現上面的實驗情況嗎?
發佈了727 篇原創文章 · 獲贊 543 · 訪問量 185萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章