docker入門加實戰—docker資料卷

2023-10-14 06:01:18

docker入門加實戰—docker資料卷

容器是隔離環境,容器內程式的檔案、設定等都在容器的內部,要讀寫容器內的檔案非常不方便。

因此,容器提供程式的執行環境,但是程式執行產生的資料、程式執行依賴的設定都應該與容器進行解耦

什麼是資料卷

資料卷(volume)是一個虛擬目錄,是容器內目錄宿主機目錄之間對映的橋樑。

以Nginx為例,我們知道Nginx中有兩個關鍵的目錄:

  • html:放置一些靜態資源;
  • conf:放置組態檔;

如果我們要讓Nginx代理我們的靜態資源,最好是放到html目錄;如果我們要修改Nginx的設定,最好是找到conf下的nginx.conf檔案。

從dockerhub的nginx說明處,我們可以看到nginx靜態檔案的位置:

不過,容器執行的Nginx所有的檔案都在容器內部。所以我們必須利用資料卷將兩個目錄與宿主機目錄關聯,方便我們操作。如圖:

在上圖中:

  • 建立了兩個資料卷:confhtml
  • Nginx容器內部的conf目錄和html目錄分別與兩個資料卷關聯
  • 而資料卷conf和html分別指向了宿主機的/var/lib/docker/volumes/conf/_data目錄和/var/lib/docker/volumes/html/_data目錄

這樣,容器內的confhtml目錄就與宿主機的confhtml目錄關聯起來,被稱為掛載。此時,操作宿主機的/var/lib/docker/volumes/html/_data就是在操作容器內的/usr/share/nginx/html/_data目錄。只要我們將靜態資源放入宿主機對應目錄,就可以被Nginx代理了。

資料卷命令

資料卷的相關命令有:

命令 說明 檔案地址
docker volume create 建立資料卷 docker volume create
docker volume ls 檢視所有資料卷 docs.docker.com
docker volume rm 刪除指定資料卷 docs.docker.com
docker volume inspect 檢視某個資料卷的詳情 docs.docker.com
docker volume prune 清除資料卷 docker volume prune

注意:容器與資料卷的掛載要在建立容器時設定,對於建立好的容器,是不能設定資料卷的。而且建立容器的過程中,資料卷會自動建立

從需求中學習資料卷命令1

需求如下:

  • 建立Nginx容器,修改nginx容器內的html目錄下的index.html檔案內容

  • 將靜態資源部署到nginx的html目錄

注意:

1. 在執行docker run命令時,使用 -v 資料卷:容器內目錄 可以完成資料卷掛載
2. 當建立容器時,如果掛載了資料卷且資料卷不存在,會自動建立資料卷

刪掉原有的nginx容器

docker rm -f nginx

建立容器並指定資料卷

# 首先建立容器並指定資料卷,通過 -v 引數來指定資料卷
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx

檢視資料卷

docker volume ls

檢視資料卷詳情

docker volume inspect html

可以看到對映到的宿主機的目錄為

進入這個目錄,修改對應的html檔案即可。

從需求中學習資料卷命令2

需求:

  • 檢視mysql容器,判斷是否有資料卷掛載

  • 基於宿主機目錄實現MySQL資料目錄、組態檔、初始化指令碼的掛載(查閱官方映象檔案)

1. 掛載/root/mysql/data到容器內的/var/lib/mysql目錄
2. 掛載/root/mysql/init到容器內的/docker-entrypoint-initdb.d目錄
3. 掛載/root/mysql/conf到容器內的/etc/mysql/conf.d目錄

注意:

1. 在執行docker run命令時,使用 -v 本地目錄 : 容器內目錄 可以完成本地目錄掛載
2. 本地目錄必須以「/」或 "./" 開頭,如果直接以名稱開頭,會被識別為資料卷而非本地目錄
	-v mysql : /var/lib/mysql 會被識別為一個資料卷叫mysql
	-v ./mysql : /var/lib/mysql 會被識別為當前目錄下的mysql目錄

檢視MySQL容器是否有資料卷

# 檢視MySQL容器詳細資訊
docker inspect mysql
# 關注其中.Config.Volumes部分和.Mounts部分

.Config.Volumes部分:

可以發現這個容器宣告了一個本地目錄,需要掛載資料卷,但是資料卷未定義。這就是匿名卷。

.Mounts部分:

可以發現,其中有幾個關鍵屬性:

  • Name:資料卷名稱。由於定義容器未設定容器名,這裡的就是匿名卷自動生成的名字,一串hash值。
  • Source:宿主機目錄
  • Destination : 容器內的目錄

上述設定是將容器內的/var/lib/mysql目錄,這時mysql資料儲存的目錄,與資料卷0d617a75a536b8d4a7ac0705403677721e1467a9859350d908861d340009a001掛載。於是在宿主機中就有了/var/lib/docker/volumes/0d617a75a536b8d4a7ac0705403677721e1467a9859350d908861d340009a001/_data這個目錄。這就是匿名資料卷對應的目錄,其使用方式與普通資料卷沒有差別。

掛載本地目錄或檔案

資料卷的目錄結構較深,如果我們去運算元據卷目錄會不太方便。在很多情況下,我們會直接將容器目錄與宿主機指定目錄掛載。掛載語法與資料卷類似:

# 掛載本地目錄
-v 本地目錄:容器內目錄
# 掛載本地檔案
-v 本地檔案:容器內檔案

再次說明一下:
本地目錄必須以「/」或 "./" 開頭,如果直接以名稱開頭,會被識別為資料卷而非本地目錄
	-v mysql:/var/lib/mysql # 會被識別為一個資料卷叫mysql,執行時會自動建立這個資料卷
	-v ./mysql:/var/lib/mysql # 會被識別為當前目錄下的mysql目錄,執行時如果不存在會建立目錄

從檔案中可以看到,設定mysql組態檔的目錄如下:

設定初始化指令碼如下:

只有第一次才會生效

資料目錄如下:

操作演示

刪除並重新建立mysql容器,並完成本地目錄掛載:

  • 掛載/root/mysql/data到容器內的/var/lib/mysql目錄
  • 掛載/root/mysql/init到容器內的/docker-entrypoint-initdb.d目錄(初始化的SQL指令碼目錄)
  • 掛載/root/mysql/conf到容器內的/etc/mysql/conf.d目錄(這個是MySQL組態檔目錄)
  1. 刪除原來的MySQL容器

    docker rm -f mysql
    

  2. 進入root目錄

    cd ~
    
  3. 建立並執行新mysql容器,掛載本地目錄

    先提前建立這些目錄

    在 root目錄操作
    mkdir mysql
    # 進入mysql目錄
    cd mysql/
    #建立以下三個目錄
    mkdir data
    mkdir conf
    mkdir init
    

    把主備好的組態檔和指令碼放到過去:

    直接把目錄上傳到linux伺服器:

    上傳後內容如下:

    在root的家目錄執行執行如下命令

    docker run -d \
      --name mysql \
      -p 3306:3306 \
      -e TZ=Asia/Shanghai \
      -e MYSQL_ROOT_PASSWORD=123 \
      -v ./mysql/data:/var/lib/mysql \
      -v ./mysql/conf:/etc/mysql/conf.d \
      -v ./mysql/init:/docker-entrypoint-initdb.d \
      mysql
    

    可以看到data目錄有檔案了