寫在前面
本來是可以將數據存儲在 容器內部 的。但是存在容器內部,一旦容器被刪除掉或者容器毀壞(我親身經歷的痛,當時我們的大數據平臺就是運行在docker容器內,有次停電後,不管怎樣容器都起不來。以前的同事也沒有將數據映射到外面 。搞得最後我們重新導的數據,痛的領悟啊~~)。
再就是如果不將數據映射出來 ,比如要想使用容器內部的web日誌,也是比較難搞,反正不就是其它容器/服務不是很方便。
大體上來說,一般只要使用Docker都會將 重要的數據 進行持久化。
本文有任何問題,歡迎留言指正~
Docker 持久化存儲技術
默認僅在Container Layer(層) 保存的文件數據,刪除容器就沒有了
Data Volume(卷):數據卷,數據掛載相關,外掛一個存儲
這個外掛的存儲 ,即:Volume 有三種類型:
Volume 卷的三種類型:
-
Volume
Docker 自己管理的 Data Volume ,由docker後臺自動創建,我們不要去 手動 更改映射出來的文件內容。掛載點 存於主機文件系統中的某個區域docker area(linux 一般是存儲在 /var/lib/docker/volumes/ 目錄下)。這種持久化方式是很推薦的*****。
-
Bind Mounting
將當前主機目錄 與 指定的容器內部目錄進行綁定 --> 實現數據共享我們在開發的時候比較推薦這種方式,實現數據共享
Docker的 數據共享 技術 能極大提高開發人員的開發效率
配合chrome插件super auto refresh plus,邊寫代碼,邊看運行結果。相當舒服~。
-
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