1. 程式人生 > 實用技巧 >docker資料卷

docker資料卷

概述

資料卷 是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,可以提供很多有用的特性:

  • 資料卷 可以在容器之間共享和重用
  • 資料卷 的修改會立馬生效
  • 資料卷 的更新,不會影響映象
  • 資料卷 預設會一直存在,即使容器被刪除

資料卷掛載的三種方式

在Docker中,要想實現資料的持久化(所謂Docker的資料持久化即資料不隨著Container的結束而結束),需要將資料從宿主機掛載到容器中。目前Docker提供了三種不同的方式將資料從宿主機掛載到容器中:

1、volumes

Docker管理宿主機檔案系統的一部分,預設位於 /var/lib/docker/volumes 目錄中;(最常用的方式

由上圖可以知道,目前所有Container的資料都儲存在了這個目錄下邊,由於沒有在建立時指定卷,所以Docker幫我們預設建立許多匿名(就上面這一堆很長ID的名字)卷。

2、bind mounts

意為著可以儲存在宿主機系統的任意位置;(比較常用的方式

但是,bind mount在不同的宿主機系統時不可移植的,比如Windows和Linux的目錄結構是不一樣的,bind mount所指向的host目錄也不能一樣。這也是為什麼bind mount不能出現在Dockerfile中的原因,因為這樣Dockerfile就不可移植了。

3、tmpfs

掛載儲存在宿主機系統的記憶體中,而不會寫入宿主機的檔案系統;(一般都不會用的方式

三種方式的示意圖如下所示:

建立資料卷

[root@localhost ~]# docker volume create test-volume1
test-volume1
[root@localhost ~]# docker volume create test-volume2
test-volume2
[root@localhost ~]# docker volume create test-volume3
test-volume3

檢視所有的資料卷

[root@localhost ~]# docker volume ls
DRIVER              VOLUME NAME
local               test-volume1
local               test-volume2
local               test-volume3

檢視指定資料卷詳情資訊

[root@localhost ~]# docker volume inspect test-volume1
[
    {
        "CreatedAt": "2020-12-24T10:34:20+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/test-volume1/_data",
        "Name": "test-volume1",
        "Options": {},
        "Scope": "local"
    }
]

容器掛載資料卷

方式一:volumes

這裡以nginx為例,建立一個數據卷test-nginx-vol,並且將資料卷掛載到 /usr/share/nginx/html (這個目錄是yum安裝nginx的預設網頁目錄)

[root@localhost volumes]# docker volume create test-nginx-vol
test-nginx-vol
[root@localhost volumes]# docker run -d -it --name=test-nginx -p 8800:80 -v test-nginx-vol:/usr/share/nginx/html nginx
5478064f3ab2cce8f8f858806d56b47ceeea44de549db9027ac8417c8a49d26f

如果沒有通過-v指定,那麼Docker會預設幫我們建立匿名資料捲進行對映和掛載。建立好容器之後,我們可以進入容器裡面看看:

[root@localhost volumes]# docker exec -it test-nginx bash
root@5478064f3ab2:/# ls
bin  boot  dev	docker-entrypoint.d  docker-entrypoint.sh  etc	home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@5478064f3ab2:/# cd  /usr/share/nginx/html 
root@5478064f3ab2:/usr/share/nginx/html# ls
50x.html  index.html

進入宿主機建立的資料卷test-nginx-vol中,可以看看:

[root@localhost test-nginx-vol]# cd /var/lib/docker/volumes/test-nginx-vol/_data/
[root@localhost _data]# ls
50x.html  index.html

當stop並且remove當前nginx容器,會發現容器卷裡面的檔案還在,由此可見資料卷裡邊的東西是可以持久化的。

[root@localhost _data]# docker stop test-nginx
test-nginx
[root@localhost _data]# docker rm test-nginx 
test-nginx
[root@localhost _data]# ls
50x.html  index.html
[root@localhost _data]# docker volume rm test-nginx-vol 
test-nginx-vol
[root@localhost _data]# ls
[root@localhost _data]# 

使用 --mount 或者-v標記來將 資料卷 掛載到容器裡。

--mount-v的區別:

  • -v :如果宿主機上沒有這個檔案,也會自動建立
  • --mount時:宿主機中沒有這個檔案會報錯找不到這個檔案,並建立失敗

方式二:Bind Mounts

docker run -d -it --name=test-nginx -v /app/wwwroot:/usr/share/nginx/html nginx

指定了將宿主機上的 /app/wwwroot 目錄(如果沒有會自動建立)掛載到 /usr/share/nginx/html (這個目錄是yum安裝nginx的預設網頁目錄)。

這時我們再次進入容器內部看看:

[root@localhost _data]# docker run -d -it --name=test-nginx -v /app/wwwroot:/usr/share/nginx/html nginx
47a9ec3d0b3d16af216b443af26cde6d2c0e507104840aaf27a0e06545e37219
[root@localhost _data]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
47a9ec3d0b3d        nginx               "/docker-entrypoint.…"   6 seconds ago       Up 5 seconds        80/tcp              test-nginx
[root@localhost _data]# docker exec -it test-nginx bash
root@47a9ec3d0b3d:/# cd /usr/share/nginx/html
root@47a9ec3d0b3d:/usr/share/nginx/html# ls
root@47a9ec3d0b3d:/usr/share/nginx/html# 

可以看到,與volumes不同,bind mounts的方式會隱藏掉被掛載目錄裡面的內容(如果非空的話),這裡是/usr/share/nginx/html 目錄下的內容被隱藏掉了,因此我們看不到。

但是,我們可以將宿主機上的檔案隨時掛載到容器中:

[root@localhost _data]# cd /app/wwwroot
[root@localhost wwwroot]# ls
[root@localhost wwwroot]# touch index.html
[root@localhost wwwroot]# ls
index.html
[root@localhost wwwroot]# docker exec -it test-nginx bash
root@47a9ec3d0b3d:/# cd /usr/share/nginx/html
root@47a9ec3d0b3d:/usr/share/nginx/html# ls
index.html
root@47a9ec3d0b3d:/usr/share/nginx/html# 

檢視容器掛載資料卷的具體資訊

docker inspect test-nginx

資料卷 資訊在 "Mounts" Key 下面

"Mounts": [
    {
        "Type": "volume",
        "Name": "test-nginx-vol",
        "Source": "/var/lib/docker/volumes/test-nginx-vol/_data",
        "Destination": "/usr/share/nginx/html",
        "Driver": "local",
        "Mode": "z",
        "RW": true,
        "Propagation": ""
    }
],

刪除資料卷

[root@localhost ~]# docker volume rm test-volume3
test-volume3
[root@localhost ~]# docker volume ls
DRIVER              VOLUME NAME
local               test-volume1
local               test-volume2

資料卷 是被設計用來持久化資料的,它的生命週期獨立於容器,Docker 不會在容器被刪除後自動刪除 資料卷,並且也不存在垃圾回收這樣的機制來處理沒有任何容器引用的 資料卷。如果需要在刪除容器的同時移除資料卷。可以在刪除容器的時候使用 docker rm -v 這個命令。

沒有容器掛載的資料卷可能會佔據很多空間,要清理請使用以下命令

[root@localhost ~]# 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:
test-volume1
test-volume2

Total reclaimed space: 0B
[root@localhost ~]# docker volume ls
DRIVER              VOLUME NAME