日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Docker 入门系列(4)- Docker 数据管理(挂载目录、挂载文件、数据卷挂载、数据卷共享、数据卷删除、数据卷容器备份和恢复)

發布時間:2023/11/28 生活经验 35 豆豆

基于底層存儲實現,Docker 提供了三種適用于不同場景的文件系統掛載方式:Bind MountVolumeTmpfs Mount

  • Bind Mount 能夠直接將宿主操作系統中的目錄和文件掛載到容器內的文件系統中,通過指定容器外的路徑和容器內的路徑,就可以形成掛載映射關系,在容器內外對文件的讀寫,都是相互可見的。

  • Volume 也是從宿主操作系統中掛載目錄到容器內,只不過這個掛載的目錄由 Docker 進行管理,我們只需要指定容器內的目錄,不需要關心具體掛載到了宿主操作系統中的哪里。

  • Tmpfs Mount 支持掛載系統內存中的一部分到容器的文件系統里,不過由于內存和容器的特征,它的存儲并不是持久的,其中的內容會隨著容器的停止而消失。

1. Bind Mount

1.1 掛載目錄到容器

要將宿主操作系統中的目錄掛載到容器之后,我們可以在容器創建的時候通過傳遞 -v--volume 選項來指定內外掛載的對應目錄或文件。

docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html nginx:1.12

使用 -v--volume 來掛載宿主操作系統目錄的形式是 -v <host-path>:<container-path>--volume <host-path>:<container-path>,其中

  • host-path代表宿主操作系統中的目錄;
  • container-path 代表容器中的目錄;

這里需要注意的是,為了避免混淆,Docker 這里強制定義目錄時必須使用絕對路徑,不能使用相對路徑。

docker inspect 的結果里,我們可以看到有關容器數據掛載相關的信息。

$ docker inspect nginx
[{
## ......"Mounts": [{"Type": "bind","Source": "/webapp/html","Destination": "/usr/share/nginx/html","Mode": "","RW": true,"Propagation": "rprivate"}],
## ......}
]

實際操作中,Docker 還支持以只讀的方式掛載,通過只讀方式掛載的目錄和文件,只能被容器中的程序讀取,但不接受容器中程序修改它們的請求。在掛載選項 -v 后再接上 :ro 就可以只讀掛載了。

docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html:ro nginx:1.12

使用 -v 標記也可以指定掛載一個本地的已有目錄到容器中去作為數據卷 (推薦方式)。

wohu@iZ:~/docker/code$ docker run  -d -P -i -t --name python -v /home/wohu/docker/code:/opt ubuntu:16.04 
c2e114c09291abaa2c3bbd9c7318a317749ab851511d0cdd57484a7c128a19cc
wohu@iZm:~/docker/code$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c2e114c09291        ubuntu:16.04        "/bin/bash"         6 seconds ago       Up 5 seconds                            pythonwohu@iZ:~/docker/code$ docker exec -ti c2 /bin/bash
root@c2e114c09291:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@c2e114c09291:/# pwd
/
root@c2e114c09291:/# cd /opt/
root@c2e114c09291:/opt# ls
test.py
root@c2e114c09291:/opt# python test.py 
bash: python: command not found
root@c2e114c09291:/opt# cat test.py 
#!/usr/bin/env python
print "this is test py file"
root@c2e114c09291:/opt# exit
exit
wohu@iZ:~/docker/code$ cat test.py 
#!/usr/bin/env python
print "this is test py file"
# 主機環境下對 test.py 文件進行修改
wohu@iZ:~/docker/code$ echo "print 'new containers'" >> test.py 
wohu@iZ:~/docker/code$ cat test.py 
#!/usr/bin/env python
print "this is test py file"
print 'new containers'
# 進入容器查看該文件是否被修改?
wohu@iZ:~/docker/code$ docker exec -it c2 /bin/bash
root@c2e114c09291:/# cd /opt/
root@c2e114c09291:/opt# ls
test.py
root@c2e114c09291:/opt# cat test.py 
#!/usr/bin/env python
print "this is test py file"
print 'new containers'  # 該文件已經被修改
root@c2e114c09291:/opt# exit
exit
wohu@iZ:~/docker/code$

上面的命令加載主機的 /home/wohu/docker/code 目錄到容器的 /opt 目錄。這個功能在進行測試的時候十分方便,比如用戶可以將一些程序或數據放到本地目錄中,然后在容器內運行和使用。另外,本地目錄的路徑必須是絕對路徑,如果目錄不存在 Docker 會自動創建。

Docker 掛載數據卷的默認權限是讀寫(rw),用戶也可以通過 ro 指定為只讀:

docker run  -d -P -i -t --name python -v /home/xwr/docker/code:/opt:ro ubuntu:16.04 

加了 :ro 之后,容器內對所掛載數據卷內的數據就無法修改了。

1.2 掛載文件到容器

-v 標記也可以從主機掛載單個文件到容器中(不推薦) 。

docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash

這樣就可以記錄在容器輸入過的命令歷史了。注意如果直接掛載一個文件到容器,使用文件編輯工具,包括 vi 或者 sed--in-place 的時候,可能會造成文件 inode 的改變,從 Docker 1.1.0 起 這會導致報錯誤信息。

所以推薦的方式是直接掛載文件所在的目錄。

2. Tmpfs Mount

Tmpfs Mount 是一種特殊的掛載方式,它主要利用內存來存儲數據。由于內存不是持久性存儲設備,所以其帶給 Tmpfs Mount 的特征就是臨時性掛載。

與掛載宿主操作系統目錄或文件不同,掛載臨時文件目錄要通過 --tmpfs 這個選項來完成。由于內存的具體位置不需要我們來指定,這個選項里我們只需要傳遞掛載到容器內的目錄即可。

docker run -d --name webapp --tmpfs /webapp/cache webapp:latest

容器已掛載的臨時文件目錄我們也可以通過 docker inspect 命令查看。

$ docker inspect webapp
[{
## ......"Tmpfs": {"/webapp/cache": ""},
## ......}
]

掛載臨時文件首先要注意它不是持久存儲這一特性,在此基礎上,它有幾種常見的適應場景。

  • 應用中使用到,但不需要進行持久保存的敏感數據,可以借助內存的非持久性和程序隔離性進行一定的安全保障。

  • 讀寫速度要求較高,數據變化量大,但不需要持久保存的數據,可以借助內存的高讀寫速度減少操作的時間。

3. Volume mount

容器中管理數據主要有兩種方式:

  • 數據卷 (Data Volumes):容器內數據直接映射到本地主機環境;
  • 數據卷容器 (Data Volume Containers):使用特定容器維護數據卷。

3.1 數據卷掛載

數據卷的本質其實依然是宿主操作系統上的一個目錄,只不過這個目錄存放在 Docker 內部,接受 Docker 的管理。

數據卷是一個可供容器使用的特殊目錄,它將主機操作系統目錄直接映射進容器,類似于 Linux 中的 mount 操作。

數據卷有如下特性:

  • 數據卷可以在容器之間共享和重用,容器間傳遞數據將變得高效方便;
  • 對數據卷內數據的修改會立馬生效,無論是容器內操作還是本地操作;
  • 對數據卷的更新不會影響鏡像,解耦了應用和數據;
  • 數據卷會一直存在,直到沒有容器使用,可以安全地卸載它;

在使用數據卷進行掛載時,我們不需要知道數據具體存儲在了宿主操作系統的何處,只需要給定容器中的哪個目錄會被掛載即可。

我們依然可以使用 -v--volume 選項來定義數據卷的掛載。在用 docker run 命令的時候,使用 -v 標記可以在容器內創建一個數據卷。多次重復使用 -v 標記可以創建多個數據卷。

docker run -d --name webapp -v /webapp/storage webapp:latest

數據卷掛載到容器后,我們可以通過 docker inspect 看到容器中數據卷掛載的信息。

$ docker inspect webapp
[{
## ......"Mounts": [{"Type": "volume","Name": "2bbd2719b81fbe030e6f446243386d763ef25879ec82bb60c9be7ef7f3a25336","Source": "/var/lib/docker/volumes/2bbd2719b81fbe030e6f446243386d763ef25879ec82bb60c9be7ef7f3a25336/_data","Destination": "/webapp/storage","Driver": "local","Mode": "","RW": true,"Propagation": ""}],
## ......}
]

其中 SourceDocker 為我們分配用于掛載的宿主機目錄,其位于 Docker 的資源區域 ( 這里是默認的 /var/lib/docker ) 內。當然,我們并不需要關心這個目錄,一切對它的管理都已經在 Docker 內實現了。

為了方便識別數據卷,我們可以像命名容器一樣為數據卷命名,這里的 Name 就是數據卷的命名。在我們未給出數據卷命名的時候,Docker 會采用數據卷的 ID 命名數據卷。我們也可以通過 -v <name>:<container-path> 這種形式來命名數據卷。

docker run -d --name webapp -v appdata:/webapp/storage webapp:latest

由于 -v 選項既承載了 Bind Mount 的定義,又參與了 Volume 的定義,所以其傳參方式需要特別留意。前面提到了,-v 在定義綁定掛載時必須使用絕對路徑,其目的主要是為了避免與數據卷掛載中命名這種形式的沖突。

Volume MountBind Mount 的區別在于數據卷 Volume Mount 可以在多個容器之間共享。

下面使用 ubuntu:16.04 鏡像創建一個 web 容器,并創建一個數據卷掛載到容器的 /webapp 目錄:

wohu@iZ:~/docker$ docker run -d -P --name python -it -v /opt ubuntu:16.04
6798b1ee4ea73622dfcdaf7b2bdab8844da4d527399229417f424e755b5be11d
wohu@iZ:~/docker$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6798b1ee4ea7        ubuntu:16.04        "/bin/bash"         7 seconds ago       Up 6 seconds                            python
wohu@iZ:~/docker$ docker exec -it 67 /bin/bash
root@6798b1ee4ea7:/# pwd
/
root@6798b1ee4ea7:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@6798b1ee4ea7:/# exit
exit
wohu@iZm5egn5zptnov4j3oxh4fZ:~/docker$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6798b1ee4ea7        ubuntu:16.04        "/bin/bash"         52 seconds ago      Up 51 seconds                           python

-P 是將容器服務暴露的端口,是自動映射到本地主機的臨時端口。

3.2 數據卷共享

由于數據卷的命名在 Docker 中是唯一的,所以我們很容易通過數據卷的名稱確定數據卷,這就讓我們很方便的讓多個容器掛載同一個數據卷了。

$ sudo docker run -d --name webapp -v html:/webapp/html webapp:latest
$ sudo docker run -d --name nginx -v html:/usr/share/nginx/html:ro nginx:1.12

我們使用 -v 選項掛載數據卷時,如果數據卷不存在,Docker 會為我們自動創建和分配宿主操作系統的目錄,而如果同名數據卷已經存在,則會直接引用。

如果有朋友覺得這樣對數據卷的操作方式還不夠直接和準確,我們還可以通過 docker volume 下的幾個命令專門操作數據卷。

通過 docker volume create 我們可以不依賴于容器獨立創建數據卷。

$ sudo docker volume create appdata

通過 docker volume ls 可以列出當前已創建的數據卷。

$ sudo docker volume ls
DRIVER              VOLUME NAME
local               html
local               appdata

3.3 刪除數據卷

我們可以直接通過 docker volume rm 來刪除指定的數據卷。

docker volume rm appdata

在刪除數據卷之前,我們必須保證數據卷沒有被任何容器所使用 ( 也就是之前引用過這個數據卷的容器都已經刪除 ),否則 Docker 不會允許我們刪除這個數據卷。

在 docker rm 刪除容器的命令中,我們可以通過增加 -v 選項來刪除容器關聯的數據卷。

docker rm -v webapp

如果我們沒有隨容器刪除這些數據卷,Docker 在創建新的容器時也不會啟用它們,即使它們與新創建容器所定義的數據卷有完全一致的特征。也就是說,此時它們已經變成了孤魂野鬼,純粹的占用著硬盤空間而又不受管理。

此時我們可以通過 docker volume rm 來刪除它們,但前提時你能在一堆亂碼般的數據卷 ID 中找出哪個是沒有被容器引用的數據卷。

為此,Docker 向我們提供了 docker volume prune 這個命令,它可以刪除那些沒有被容器引用的數據卷。

$ docker volume prune -f
Deleted Volumes:
af6459286b5ce42bb5f205d0d323ac11ce8b8d9df4c65909ddc2feea7c3d1d53
0783665df434533f6b53afe3d9decfa791929570913c7aff10f302c17ed1a389
65b822e27d0be93d149304afb1515f8111344da9ea18adc3b3a34bddd2b243c7
## ......

4. 數據卷容器

如果用戶需要在多個容器之間共享一些持續更新的數據,最簡單的方式是使用數據卷容器。數據卷容器也是一個容器,但是它的目的是專門用來提供數據卷供其他容器掛載。

首先,創建一個數據卷容器 dbdata,并在其中創建一個數據卷掛載到 /dbdata (沒有該目錄會自動創建),并在其中創建一個dbdata.txt 文件。

wohu@iZm5egn5zptnov4j3oxh4fZ:~/docker/code$ docker run -ti --name dbdata -v /dbdata ubuntu:16.04
root@531dabd7eaa8:/# cd /d
dbdata/ dev/    
root@531dabd7eaa8:/# cd /dbdata/
root@531dabd7eaa8:/dbdata# touch dbdata.txt
root@531dabd7eaa8:/dbdata# echo "this is dbdata.txt" > dbdata.txt 
root@531dabd7eaa8:/dbdata# exit
exit
wohu@iZm5egn5zptnov4j3oxh4fZ:~/docker/code$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
531dabd7eaa8        ubuntu:16.04        "/bin/bash"         50 seconds ago      Exited (0) 4 seconds ago                       dbdata
c2e114c09291        ubuntu:16.04        "/bin/bash"         17 minutes ago      Up 17 minutes                                  python

然后,可以在其他容器中使用 --volumes-from 來掛載 dbdata 容器中的數據卷,例如創建 db1db2 兩個容器,并從 dbdata 容器掛載數據卷:

$ docker run -it --volumes-from dbdata --name db1 ubuntu
$ docker run -it --volumes-from dbdata --name db2 ubuntu

此時,容器 db1db2 都掛載同一個數據卷到相同的 /dbdata 目錄。三個容器任何一方在該目錄下的寫入,其他容器都可以看到。

例如,在 dbdata 容器中創建一個 test 文 件,如下所示:

wohu@iZ:~/docker/code$ docker run -ti --name db1 --volumes-from dbdata  ubuntu:16.04
root@eb16116ec6ae:/# ls
bin  boot  dbdata  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@eb16116ec6ae:/# cd dbdata/
root@eb16116ec6ae:/dbdata# ls
dbdata.txt
root@eb16116ec6ae:/dbdata# cat dbdata.txt 
this is dbdata.txt
root@eb16116ec6ae:/dbdata# exit           
exit
wohu@iZm5egn5zptnov4j3oxh4fZ:~/docker/code$ docker run -ti --name db2 --volumes-from dbdata  ubuntu:16.04
root@c178579dcdb2:/# ls 
bin  boot  dbdata  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@c178579dcdb2:/# cd dbdata/
root@c178579dcdb2:/dbdata# ls
dbdata.txt
root@c178579dcdb2:/dbdata# cat dbdata.txt 
this is dbdata.txt
root@c178579dcdb2:/dbdata# exit
exit
wohu@iZm5egn5zptnov4j3oxh4fZ:~/docker/code$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
c178579dcdb2        ubuntu:16.04        "/bin/bash"         25 seconds ago      Exited (0) 7 seconds ago                        db2
eb16116ec6ae        ubuntu:16.04        "/bin/bash"         57 seconds ago      Exited (0) 41 seconds ago                       db1
531dabd7eaa8        ubuntu:16.04        "/bin/bash"         4 minutes ago       Exited (0) 3 minutes ago                        dbdata
c2e114c09291        ubuntu:16.04        "/bin/bash"         21 minutes ago      Up 20 minutes                                   python
wohu@iZm5egn5zptnov4j3oxh4fZ:~/docker/code$ 

可以多次使用 --volumes-from 參數來從多個容器掛載多個數據卷。還可以從其他已經掛載了容器卷的容器來掛載數據卷。

注意:使用 --volumes-from 參數所掛載數據卷的容器自身并不需要保持在運行狀態。如果刪除了掛載的容器 (包括 dbdata、db1 和 db2),數據卷并不會被自動刪除。如果要刪除一個數據卷,必須在刪除最后一個還掛載著它的容器時顯式使用 docker rm -v 命令來指定同時刪除關聯的容器。

5. 利用數據卷容器來遷移數據

可以利用數據卷容器對其中的數據卷進行備份、恢復、以實現數據的遷移。

5.1 備份

使用下面的命令來備份 dbdata 數據卷容器內的數據卷:

docker run --volumes-from dbdata -v (pwd):/backup --name worker ubuntu tarcvf /backup/backup.tar /dbdata

首先利用 ubuntu 鏡像創建了一個容器 worker。使用 --volumes-from dbdata 參數來讓 worker 容器掛載 dbdata 容器的數據卷(即 dbdata 數據卷)。

使用 -v$(pwd):/backup 參數來掛載本地的當前目錄到 worker 容器的 /backup 目錄。worker 容器啟動后,使用了 tar cvf /backup/backup.tar /dbdata 命令來將 /dbdata 下內容備份為容器內的 /backup/backup.tar,即宿主主機當前目錄下的 backup.tar

$ sudo docker run --rm --volumes-from appdata -v /backup:/backup ubuntu tar cvf /backup/backup.tar /webapp/storage

通過 --rm 選項,我們可以讓容器在停止后自動刪除,而不需要我們再使用容器刪除命令來刪除它,這對于我們使用一些臨時容器很有幫助。

5.2 恢復

如果要將數據恢復到一個容器,可以按照下面的步驟操作。首先創建一個帶有數據卷的容器 dbdata2

docker run -v /dbdata --name dbdata2 ubuntu /bin/bash

然后創建另一個新的容器,掛載 dbdata2 的容器,并使用 untar 解壓備份文件到所掛載的容器卷中。

docker run --volumes-from dbdata2 -v (pwd):/backup busybox tar xvf /backup/backup.tar

或者下面命令

$ docker run --rm --volumes-from appdata -v /backup:/backup ubuntu tar xvf /backup/backup.tar -C /webapp/storage --strip

總結

以上是生活随笔為你收集整理的Docker 入门系列(4)- Docker 数据管理(挂载目录、挂载文件、数据卷挂载、数据卷共享、数据卷删除、数据卷容器备份和恢复)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。