寫在前面
本來是可以將數(shù)據(jù)存儲在 容器內(nèi)部 的掷贾。但是存在容器內(nèi)部隙姿,一旦容器被刪除掉或者容器毀壞(我親身經(jīng)歷的痛,當(dāng)時(shí)我們的大數(shù)據(jù)平臺就是運(yùn)行在docker容器內(nèi)唉擂,有次停電后餐屎,不管怎樣容器都起不來。以前的同事也沒有將數(shù)據(jù)映射到外面 玩祟。搞得最后我們重新導(dǎo)的數(shù)據(jù)腹缩,痛的領(lǐng)悟啊~~)。
再就是如果不將數(shù)據(jù)映射出來 空扎,比如要想使用容器內(nèi)部的web日志藏鹊,也是比較難搞,反正不就是其它容器/服務(wù)不是很方便转锈。
大體上來說盘寡,一般只要使用Docker都會將 重要的數(shù)據(jù) 進(jìn)行持久化。
本文有任何問題撮慨,歡迎留言指正~
Docker 持久化存儲技術(shù)
默認(rèn)僅在Container Layer(層) 保存的文件數(shù)據(jù)竿痰,刪除容器就沒有了
Data Volume(卷):數(shù)據(jù)卷,數(shù)據(jù)掛載相關(guān)砌溺,外掛一個(gè)存儲
這個(gè)外掛的存儲 菇曲,即:Volume 有三種類型:
Volume 卷的三種類型:
-
Volume
Docker 自己管理的 Data Volume ,由docker后臺自動創(chuàng)建,我們不要去 手動 更改映射出來的文件內(nèi)容抚吠。掛載點(diǎn) 存于主機(jī)文件系統(tǒng)中的某個(gè)區(qū)域docker area(linux 一般是存儲在 /var/lib/docker/volumes/ 目錄下)常潮。這種持久化方式是很推薦的*****。
-
Bind Mounting
將當(dāng)前主機(jī)目錄 與 指定的容器內(nèi)部目錄進(jìn)行綁定 --> 實(shí)現(xiàn)數(shù)據(jù)共享我們在開發(fā)的時(shí)候比較推薦這種方式楷力,實(shí)現(xiàn)數(shù)據(jù)共享
Docker的 **數(shù)據(jù)共享** 技術(shù) 能極大提高開發(fā)人員的開發(fā)效率
配合chrome插件super auto refresh plus喊式,邊寫代碼孵户,邊看運(yùn)行結(jié)果。相當(dāng)舒服~岔留。
- tmpfs mount(Linux中):存于內(nèi)存中(注意夏哭,并不是持久化到磁盤)。在容器的生命周期中献联,它能被容器用來存放非持久化的狀態(tài)或敏感信息
在這里插入圖片描述
上圖 卷的三種類型竖配,后文主要根據(jù)代碼來講解這幾種類型
Volume 相關(guān)的常用命令:
列出所有卷:docker volume ls
刪除某個(gè)卷:docker volume rm 卷名
刪除所有未使用的卷:docker volume prune # 慎用
創(chuàng)建:docker volume create
查看某個(gè)卷的元信息:docker volume inspect 卷名
容器數(shù)據(jù) 持久化 實(shí)操
類型一:Volume
如果沒有顯式創(chuàng)建卷,一個(gè)卷會在最開始 掛載<VOLUME["/var/lib/mysql"] > 時(shí)被創(chuàng)建里逆。當(dāng)容器停止時(shí)进胯,卷仍然存在。多個(gè)容器可以通過read-write或read-only的方式使用同一個(gè)卷原押。只有在顯式刪除時(shí)胁镐,卷才會被刪除。
查看官方mysql Dockerfile 中定義的持久化存儲方式:
https://github.com/docker-library/mysql/blob/6952c5d5a9889311157362c528d65dc2e37ff660/5.7/Dockerfile
發(fā)現(xiàn)是通過 VOLUME["/var/lib/mysql"] 這樣的方式將數(shù)據(jù)持久化到本地的
意思是指诸衔,需要將容器內(nèi)部/var/lib/mysql 目錄下的數(shù)據(jù) 映射出去
不指定其實(shí)是不會將數(shù)據(jù)映射出來的盯漂。
映射出來的位置是在/var/lib/docker/volumes/ ,他會自己在該目錄下生成一個(gè)volume ID
實(shí)際的數(shù)據(jù)就是保存在其中的笨农。
代碼驗(yàn)證上面這段話:
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
回到本地主機(jī):
docker volume ls
docker volume inspect [volume ID]
詳細(xì)信息中可以看見掛載點(diǎn)
cd 進(jìn)去就缆,可以看見實(shí)際的數(shù)據(jù)庫文件是真實(shí)存在的。
/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]#
其實(shí)這個(gè)時(shí)候你把容器停止谒亦,刪除容器违崇。數(shù)據(jù)庫的文件還是會在本地保留的
# 強(qiáng)制刪除運(yùn)行中的容器
docker rm -f mysql1
# 刪除volume
docker volume rm VOLUME NAME
【升級1】
上面的方式有一個(gè)不好的地方就是:由于沒有指定映射的對應(yīng)目錄,自動為我們生成了一個(gè)很長的Volume ID,
這個(gè)其實(shí)是不太好管理的诊霹。最好的方式是羞延,我們自己指定名稱。
具體如下:
通過-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 ~]#
發(fā)現(xiàn)是我們自己指定的名稱mysql
【升級2】
上面的還有一個(gè)不好的一點(diǎn) 就是不太方便移植映射出來脾还,
我們?nèi)绻梢詫⒂成涑鰜淼哪夸浿付ǖ?Dockerfile 同一級目錄下就更好了伴箩,
要想實(shí)現(xiàn)這個(gè) 可以通過編寫 docker-compose.yml 文件,在文件中定義volume
volume這種方式可以很好的將數(shù)據(jù)持久化的本地文件系統(tǒng)中鄙漏,【推薦】
類型二:Bind Mounting
將當(dāng)前目錄外部 與 指定的容器內(nèi)部目錄進(jìn)行綁定 --> 實(shí)現(xiàn)數(shù)據(jù)共享
案例中 實(shí)現(xiàn)容器內(nèi)部 /usr/share/nginx/html 與 本機(jī)主機(jī) /root/docker-nginx
兩個(gè)目錄下的文件共享
案例:
[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]#
# 創(chuàng)建容器
將當(dāng)前目錄與 指定的容器內(nèi)部目錄進(jìn)行綁定
[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#
后面我可能會根據(jù) SpringBoot 單獨(dú)寫一篇文章 嗤谚,看看到底這個(gè)代碼共享 該怎么去做。
本文比較基礎(chǔ)怔蚌,后面我再寫一下關(guān)于 容錯巩步、 備份、恢復(fù)桦踊、遷移數(shù)據(jù)卷 相關(guān)的東西椅野。
盡情期待~
有什么問題,歡迎留言討論~~
更多文章:系統(tǒng)學(xué)習(xí)Docker 不迷路:https://blog.csdn.net/liuge36/category_7651616.html