Docker 容器數據 持久化(系統學習Docker05)

寫在前面

本來是可以將數據存儲在 容器內部 的。但是存在容器內部,一旦容器被刪除掉或者容器毀壞(我親身經歷的痛,當時我們的大數據平臺就是運行在docker容器內,有次停電後,不管怎樣容器都起不來。以前的同事也沒有將數據映射到外面 。搞得最後我們重新導的數據,痛的領悟啊~~)。
再就是如果不將數據映射出來 ,比如要想使用容器內部的web日誌,也是比較難搞,反正不就是其它容器/服務不是很方便。

大體上來說,一般只要使用Docker都會將 重要的數據 進行持久化。

本文有任何問題,歡迎留言指正~

Docker 持久化存儲技術

默認僅在Container Layer(層) 保存的文件數據,刪除容器就沒有了

Data Volume(卷):數據卷,數據掛載相關,外掛一個存儲

在這裏插入圖片描述
這個外掛的存儲 ,即:Volume 有三種類型:

Volume 卷的三種類型:

  1. Volume
    Docker 自己管理的 Data Volume ,由docker後臺自動創建,我們不要去 手動 更改映射出來的文件內容。掛載點 存於主機文件系統中的某個區域docker area(linux 一般是存儲在 /var/lib/docker/volumes/ 目錄下)。

    這種持久化方式是很推薦的*****。

  2. Bind Mounting
    將當前主機目錄 與 指定的容器內部目錄進行綁定 --> 實現數據共享

    我們在開發的時候比較推薦這種方式,實現數據共享

    Docker的 數據共享 技術 能極大提高開發人員的開發效率

    配合chrome插件super auto refresh plus,邊寫代碼,邊看運行結果。相當舒服~。

  3. tmpfs mount(Linux中):存於內存中(注意,並不是持久化到磁盤)。在容器的生命週期中,它能被容器用來存放非持久化的狀態或敏感信息
    在這裏插入圖片描述
    上圖 卷的三種類型,後文主要根據代碼來講解這幾種類型

Volume 相關的常用命令:

列出所有卷:docker volume ls

刪除某個卷:docker volume rm 卷名
刪除所有未使用的卷:docker volume prune # 慎用
創建:docker volume create

查看某個卷的元信息:docker volume inspect 卷名



容器數據 持久化 實操

類型一:Volume
如果沒有顯式創建卷,一個卷會在最開始 掛載<VOLUME["/var/lib/mysql"] > 時被創建。當容器停止時,卷仍然存在。多個容器可以通過read-write或read-only的方式使用同一個卷。只有在顯式刪除時,卷纔會被刪除。

查看官方mysql Dockerfile 中定義的持久化存儲方式:
https://github.com/docker-library/mysql/blob/6952c5d5a9889311157362c528d65dc2e37ff660/5.7/Dockerfile

發現是通過 VOLUME["/var/lib/mysql"] 這樣的方式將數據持久化到本地的 
意思是指,需要將容器內部/var/lib/mysql 目錄下的數據 映射出去 
不指定其實是不會將數據映射出來的。
映射出來的位置是在/var/lib/docker/volumes/  ,他會自己在該目錄下生成一個volume ID
實際的數據就是保存在其中的。

代碼驗證上面這段話:
docker volume ls
docker run -d --name mysql1 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.7 
[root@localhost ~]# docker ps
cef34ac36e63        mysql:5.7           "docker-entrypoint.s…"   16 seconds ago      Up 15 seconds       3306/tcp, 33060/tcp                          mysql1
[root@localhost ~]# 
docker exec -it mysql1 bash
mysql -u root
create database test1;
quit
exit
回到本地主機:
docker volume ls 
docker volume inspect [volume ID]
詳細信息中可以看見掛載點
cd 進去,可以看見實際的數據庫文件是真實存在的。
/var/lib/docker/volumes/1b7400bf5cca58f06957e865ab7c072b4cd5961c56d536357fb69575985ecbac/_data
[root@localhost _data]# ls
auto.cnf    client-cert.pem  ibdata1      ibtmp1              private_key.pem  server-key.pem
ca-key.pem  client-key.pem   ib_logfile0  mysql               public_key.pem   sys
ca.pem      ib_buffer_pool   ib_logfile1  performance_schema  server-cert.pem  test1
[root@localhost _data]# 

其實這個時候你把容器停止,刪除容器。數據庫的文件還是會在本地保留的
# 強制刪除運行中的容器
docker rm -f mysql1 
# 刪除volume 
docker volume rm VOLUME NAME 

【升級1】
上面的方式有一個不好的地方就是:由於沒有指定映射的對應目錄,自動爲我們生成了一個很長的Volume ID,
這個其實是不太好管理的。最好的方式是,我們自己指定名稱。

具體如下:
通過-v 指定映射
docker run -d -v mysql:/var/lib/mysql --name mysql2 -e MYSQL_ALLOW_EMPTY_PASSWORD=true mysql:5.7 
[root@localhost ~]# docker volume ls
DRIVER              VOLUME NAME
local               mysql
[root@localhost ~]# 
發現是我們自己指定的名稱mysql 

【升級2】
上面的還有一個不好的一點 就是不太方便移植映射出來,
我們如果可以將映射出來的目錄指定到 Dockerfile 同一級目錄下就更好了,
要想實現這個 可以通過編寫 docker-compose.yml 文件,在文件中定義volume

volume這種方式可以很好的將數據持久化的本地文件系統中,【推薦】

類型二:Bind Mounting
將當前目錄外部 與 指定的容器內部目錄進行綁定 --> 實現數據共享

案例中 實現容器內部 /usr/share/nginx/html 與 本機主機 /root/docker-nginx
兩個目錄下的文件共享

案例:


[root@localhost ~]# mkdir docker-nginx
[root@localhost ~]# cd docker-nginx/

[root@localhost docker-nginx]# vim Dockerfile 
FROM nginx:latest
WORKDIR /usr/share/nginx/html
COPY index.html index.html

[root@localhost docker-nginx]# docker build -t liuge36docker/my-nginx .
Sending build context to Docker daemon  3.072kB
Step 1/3 : FROM nginx:latest
 ---> 2073e0bcb60e
Step 2/3 : WORKDIR /usr/share/nginx/html
 ---> Running in 8bdefed78445
Removing intermediate container 8bdefed78445
 ---> 747647be78f1
Step 3/3 : COPY index.html index.html
 ---> b6a5afe9dcf8
Successfully built b6a5afe9dcf8
Successfully tagged liuge36docker/my-nginx:latest
[root@localhost docker-nginx]# 


# 創建容器
將當前目錄與 指定的容器內部目錄進行綁定 
[root@localhost docker-nginx]# docker rm -f web
web
[root@localhost docker-nginx]# docker run -d -v $(pwd):/usr/share/nginx/html -p 8777:80 --name web liuge36docker/my-nginx
4822d9626b36c2b539527a9ba8d9cdebfaee19762b02f957559e4f2ae6e2d281

[root@localhost docker-nginx]# docker exec -it web /bin/bash
root@4822d9626b36:/usr/share/nginx/html# ls
Dockerfile  index.html
root@4822d9626b36:/usr/share/nginx/html# touch hello.txt
root@4822d9626b36:/usr/share/nginx/html# exit
exit

[root@localhost docker-nginx]# ls
Dockerfile  hello.txt  index.html
[root@localhost docker-nginx]# echo  "1111" >> hello.txt 
[root@localhost docker-nginx]# docker exec -it web /bin/bash

root@4822d9626b36:/usr/share/nginx/html# cat hello.txt 
1111
root@4822d9626b36:/usr/share/nginx/html#

後面我可能會根據 SpringBoot 單獨寫一篇文章 ,看看到底這個代碼共享 該怎麼去做。

本文比較基礎,後面我再寫一下關於 容錯、 備份、恢復、遷移數據卷 相關的東西。

盡情期待~

有什麼問題,歡迎留言討論~~

更多文章:系統學習Docker 不迷路:https://blog.csdn.net/liuge36/category_7651616.html

發佈了161 篇原創文章 · 獲贊 31 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章