在瞭解Docker數據持久化以前,須要對Docker的存儲類型有一個簡單的瞭解,執行如下命令便可看出:html
[root@docker01 ~]# docker info //查看Docker的詳細信息 Containers: 1 //一共有幾個容器 Running: 1 //正在運行的有幾個容器 Paused: 0 //掛起、暫停的有幾個容器 Stopped: 0 //中止的有幾個容器 Images: 2 //有幾個鏡像 Server Version: 18.09.0 //docker的版本信息 Storage Driver: overlay2 //存儲驅動類型爲overlay2 Backing Filesystem: xfs //支持的文件系統:xfs Supports d_type: true Native Overlay Diff: false Logging Driver: json-file Cgroup Driver: cgroupfs Plugins: Volume: local //本地存儲 Network: bridge host macvlan null overlay //支持的網絡類型 Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: runc Default Runtime: runc Init Binary: docker-init containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd init version: fec3683 Security Options: seccomp Profile: default Kernel Version: 3.10.0-514.el7.x86_64 //內核信息 Operating System: CentOS Linux 7 (Core) //操做系統 OSType: linux //操做系統類型 Architecture: x86_64 CPUs: 4 //CPU個數 Total Memory: 3.686GiB //內存容量 Name: docker01 ID: X6ON:W73P:YWXD:NV7U:3C2J:RXH3:GNPO:SYIP:FF53:CNFN:HSN3:EZG2 Docker Root Dir: /var/lib/docker Debug Mode (client): false Debug Mode (server): false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 127.0.0.0/8 Registry Mirrors: //採用的加速器信息 https://weimtsj8.mirror.aliyuncs.com/ Live Restore Enabled: false Product License: Community Engine
在docker中實現數據持久化有兩種方式:Bind mount和Docker Manager Volume。linux
Bind mount和Docker Manager Volume的區別:nginx
Bind mount數據持久化的方式,若是是掛載本地的一個目錄,則容器內對應的目錄下的內容會被本地的目錄覆蓋掉,而Docker Manager Volume這種方式則不會,無論哪一種方式的持久化,在容器被銷燬後,本地的數據都不會丟失。
使用「-v」選項掛載時,Bind mount明確指定了要掛載docker host本地的某個目錄到容器中,而Docker Manager Volume則只指定了要對容器內的某個目錄進行掛載,而掛載的是docker host本地的哪一個目錄,則是由docker來管理的。web
如下數據卷容器掛載的方式就是Bind mount實現方式。docker
實現的大概思路以下:apache
1.運行一個容器做爲數據卷容器,掛載本地目錄到容器內的本地目錄,無需所掛載的源目錄或目標掛載點是否存在,docker會自動建立相應的目錄的,也無需考慮使用哪一個鏡像來運行這個容器,任意鏡像均可以;
2.以後不管運行多少容器,均可以使用--volumes-from選項來指定第一個運行的容器進行數據持久化;
3.實現的效果爲:掛載數據卷容器實現數據持久化的容器,會自動將數據卷容器掛載的本地目錄掛載到該容器自己(自己的掛載點與數據卷容器的掛載點自動保持一致),也僅僅只會掛載數據卷容器實現了數據持久化的目錄到本身自己,而不是數據卷容器的所有目錄。json
上面實現的效果可能我表達的不夠好,舉個例子 :
有A、B、C這三個容器,其中A做爲數據卷容器,掛載了本地的/data/web01和/data/web02這兩個目錄到容器內的/usr/share/nginx/html/和/data這兩個目錄。
容器B和容器C在運行之初,經過--volumes-from選項來指定容器A的名稱或ID,那麼最終實現的效果就是,A、B、C這三個容器內都會存在/usr/share/nginx/html及/data這兩個目錄,而且是實現了數據持久化的,對應的本地目錄都是/data/web01和/data/web02。vim
持久化存儲:本質上是DockerHost文件系統中的目錄或文件,可以直接被Mount到容器的文件系統中。在運行容器時,能夠經過-v 實現。瀏覽器
Bind mount的特色:網絡
Data Volume是目錄或文件,不能是沒有格式化的磁盤(塊設備);
容器能夠讀寫volume中的數據;
隨源文件變化而變化;
volume數據能夠永久保存,即便使用它的容器已經被銷燬;
示例:
[root@localhost ~]# cd /tmp/ [root@localhost tmp]# mkdir /html [root@localhost tmp]# echo "huan ying ni zjz" >> /html/index.html //建立測試頁面 [root@localhost tmp]# docker run -itd --name testweb -p 80:80 -v /html:/usr/share/nginx/html nginx:latest //運行容器並使用「-v」選項指定掛載目錄,前面爲docker host的目錄,「:」後面爲容器中的目錄 [root@localhost tmp]# curl 127.0.0.1 //能夠看到掛載已經生效 huan ying ni zjz [root@localhost tmp]# echo "hello" >> /html/index.html [root@localhost tmp]# curl 127.0.0.1 //這種方式能夠看出當源文件發生變化時,目標文件也會隨之發生變化 huan ying ni zjz hello [root@localhost tmp]# docker inspect testweb //查看容器的詳細信息
注意:
DockerHost上須要被掛着的源文件或目錄,必須是已經存在,不然,當作的一個目錄掛着到容器中;
默認掛載到容器內的文件,容器是有讀寫權限。能夠在運行容器「-v」選項後邊加「:ro」 選項來限制容器的寫入權限;
能夠掛載單獨的文件到容器內部,使用場景:若是不想對整個目錄進行覆蓋,而只但願添加某個文件,就可使用掛載單個文件;
示例:
[root@docker ~]# docker run -itd --name test1 -v /usr/share/nginx/html nginx:latest //這種方式「-v」選項後,只需添加容器中的目錄便可 [root@docker ~]# docker inspect test1
[root@docker~]#ls /var/lib/docker/volumes/46d00301afb2b9c8d5279475d50d9242470af37969fa52338e916de1e35a6e93/_data/ 50x.html index.html //能夠看出宿主機上的目錄就是容器中掛載的目錄
這種方式特色:
會隨着源文件的變化而變化,跟Bind mount效果是同樣的!
刪除容器的操做,默認不會對dockerhost主機上的原文件進行刪除,若是想要在刪除容器是將原文件刪除,能夠在刪除容器時添加「-v」選項,(通常狀況下不建議使用,由於文件有可能被其餘容器就使用);
Volume container:給其餘容器提供volume存儲卷的容器。而且它能夠提供bind mount,也能夠提供docker manager volume。
[root@docker ~]# docker create --name vc_data -v /html:/usr/share/nginx/html busybox:latest //建立一個容器(無須運行) [root@docker ~]# docker run -itd --name test3 -P --volumes-from vc_data nginx:latest //使用「--volumes-from」來掛載vc_data容器中的數據間到新的容器test3 [root@docker ~]# docker ps //查看其映射的端口 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 0c0429f3e8c0 nginx:latest "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:32768->80/tcp test3 [root@docker ~]# curl 127.0.0.1:32768 //測試效果 huan ying ni zjz hello
注意:以上方式在源目錄刪除後,容器中的數據也會發生丟失現象!
能夠採用編寫dockerfile文件的方式,將目錄或文件寫到鏡像中,而後根據鏡像生成容器,纔可保證原數據丟失,容器中的數據不會發生變化!
因爲這種方式隨機性、靈活性太差,這裏就很少作介紹了這樣就能夠經過數據卷容器實現容器之間的數據共享。
經過以上機制,即便容器在運行過程當中出現故障,用戶也不用擔憂數據發生丟失。若是發生意外,只需快速從新建立容器便可!
注意:生產環境中最注重的就是存儲的可靠性,以及存儲的可動態擴展性,必定要在作數據卷時考慮到這一點,在這方面比較出色的還要數GFS文件系統了,我上面只是作了簡單的配置,若在生產環境中,必定要好好考慮,就好比上面作的鏡像卷容器,就能夠在宿主機本地掛載GFS文件系統,而後建立鏡像卷容器時,將掛載GFS的目錄映射到容器中的鏡像卷,這樣纔是一個合格的鏡像卷容器。
Bind Mount 和 Docker Manager Volume的特色;
docket1 | docker2 | docker3 |
---|---|---|
httpd | httpd | nfs |
要求:docker01和docker02的主目錄,是同樣的。
docker3的操做
[root@nfs ~]# yum -y install nfs-utils #安裝nfs [root@nfs ~]# mkdir /datashare #建立共享目錄 [root@nfs ~]# vim /etc/exports #設置權限 /datashare *(rw,sync,no_root_squash) [root@nfs ~]# systemctl start rpcbind [root@nfs ~]# systemctl enable rpcbind [root@nfs ~]# systemctl start nfs-server.service #啓動 [root@nfs ~]# systemctl enable nfs-server.service #開機自啓 [root@nfs ~]# showmount -e #驗證 Export list for nfs: /datashare * [root@nfs ~]# cd /datashare/ [root@nfs datashare]# touch 123.txt #建立測試文件 [root@nfs datashare]# echo "12312321312" > 123.txt [root@nfs datashare]# cat 123.txt 12312321312 [root@nfs datashare]# echo "hell world" > index.html
docker1上的操做
#也需安裝nfs [root@docker1 ~]# showmount -e 192.168.10.54 #驗證 Export list for 192.168.10.54: /datashare * [root@docker1 ~]# mkdir /htdocs #建立目錄 [root@docker1 htdocs]# mount -t nfs 192.168.10.54:/datashare /htdocs #將/htdocs目錄掛載到192.168.10.54:/datashare 下 [root@docker1 ~]# cd /htdocs/ [root@docker1 htdocs]# pwd /htdocs [root@docker1 htdocs]# ls 123.txt index.html [root@docker1 htdocs]# cat 123.txt 12312321312 [root@docker1 ~]# docker run -itd --name web1 -P -v /htdocs:/usr/local/apache2/htdocs httpd:latest [root@docker1 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES ed9710a468a2 httpd:latest "httpd-foreground" 43 seconds ago Up 41 seconds 0.0.0.0:32768->80/tcp web1
docker2上的操做和docker1操做同樣
#也需安裝nfs [root@docker2 ~]# showmount -e 192.168.10.54 #驗證 Export list for 192.168.10.54: /datashare * [root@docker2 ~]# mkdir /htdocs [root@docker2 htdocs]# mount -t nfs 192.168.10.54:/datashare /htdocs [root@docker2 ~]# cd /htdocs/ [root@docker2 htdocs]# pwd /htdocs [root@docker2 htdocs]# ls 123.txt index.html [root@docker2 htdocs]# cat 123.txt 12312321312 [root@docker2 htdocs]# docker run -itd --name web2 -P -v /htdocs:/usr/local/apache2/htdocs httpd:latest [root@docker2 htdocs]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2a5ddae0894d httpd:latest "httpd-foreground" 7 seconds ago Up 5 seconds 0.0.0.0:32769->80/tcp web2
此時,用瀏覽器訪問,兩個WEB服務的主界面是同樣。但若是,NFS服務 器上的源文件丟失,則兩個web服務都會異常
想辦法將源數據寫入鏡像內,在基於鏡像作一個vc_data容器,因此咱們 在docker01和docker02上先手動建立鏡像
docker1上操做
[root@docker1 htdocs]# vim Dockerfile FROM busybox ADD index.html /usr/local/apache2/htdocs/index.html VOLUME /usr/local/apache2/htdocs [root@docker1 htdocs]# docker build -t back_data . [root@docker1 htdocs]# docker create --name back_container1 back_data:latest [root@docker1 htdocs]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE back_data latest bfc2314995b5 24 seconds ago 1.22MB [root@docker1 htdocs]# docker run -itd --name web3 -P --volumes-from back_container1 httpd:latest [root@docker1 htdocs]# docker inspect web3
**總結:<br/>1)解決容器跨主機數據共享的方案: NFS<br/>2)容器與容器的數據共享: 基於某個容器而來(--volumes-from選 項),意味着這些容器和vc容器的數據存儲是同樣的。**