Docker系列:04.數據共享與持久化
Docker的鏡像是分層設計的,底層是只讀的,通過鏡像其的容器添加了一層可讀寫的文件系統,用戶寫入的數據都保存在這一層當中,如果要將寫入的數據永久生效,需要將其提交為一個鏡像然後通過這個鏡像在啟動實例,然後就會給這個啟動的實例添加一層可讀寫的文件系統,以此類推,目前docker將數據存儲分為兩種方式,數據卷和數據容器卷,具體如下:
04.1、數據卷
數據卷是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,可以提供很多有用的特性:
- 數據卷可以在容器之間共享和重用
- 對數據卷的修改會立馬生效
- 對數據卷的更新,不會影響鏡像
- 數據卷默認會一直存在,即使容器被刪除
註意:數據卷 的使用,類似於 Linux 下對目錄或文件進行 mount,鏡像中的被指定為掛載點的目錄中的文件會隱藏掉,能顯示看的是掛載的 數據卷。
選擇-v
還是-–mount
參數
Docker 新用戶應該選擇 --mount 參數,經驗豐富的 Docker 使用者對 -v 或者 --volume 已經很熟悉了,但是推薦使用 --mount 參數。
04.1.1、啟動容器加載數據卷
- 數據卷類似一個被掛載的目錄。啟動後的docker容器可以在這個目錄進行讀寫操作,類似於遠程掛載一個NFS共享
[root@docker-server1 ~]# docker run -d --name nginx-test1 -v /data nginx [root@docker-server1 ~]# ./docker.sh nginx-test1 root@e67af30200e3:/# df -TH Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/docker-253:0-201458571-6f26313298b2d5adb230575fbaab10accb18eef2f03b12694ac6df45770c1508 xfs 11G 239M 11G 3% / tmpfs tmpfs 2.0G 0 2.0G 0% /dev tmpfs tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup /dev/mapper/centos-root xfs 51G 4.7G 47G 10% /data #被掛載的磁盤 shm
- 上面的data目錄還有47G的空間,那個這個數據目錄在物理機的位置在哪裏?
[root@docker-server1 ~]# docker inspect -f {{.Mounts}} nginx-test1 #查看掛載信息 [{50c86b4bb97c2751f781866c5298b1455e804f7af340335dc637c67f76a1d32d /var/lib/docker/volumes/50c86b4bb97c2751f781866c5298b1455e804f7af340335dc637c67f76a1d32d/_data /data local true }] #或以下方式: [root@docker-server1 ~]# docker inspect nginx-test1 #查看容器的所有信息 [root@docker-server1 ~]# docker inspect nginx-test1 |grep Source|awk -F ‘[:,]‘ ‘{print $2}‘ #過濾出掛載點 "/var/lib/docker/volumes/50c86b4bb97c2751f781866c5298b1455e804f7af340335dc637c67f76a1d32d/_data"
- 在物理機創建目錄驗證容器當中是否可以訪問並寫入數據
[root@docker-server1 _data]# pwd #在容器的目錄實際位置即物理機的數據目錄當中
/var/lib/docker/volumes/50c86b4bb97c2751f781866c5298b1455e804f7af340335dc637c67f76a1d32d/_data
[root@docker-server1 _data]# mkdir testdir
#在容器當中驗證:
root@e67af30200e3:/# ls /data/
testdir #目錄已經存在
root@e67af30200e3:/# echo "xxoo" > /data/testdir/testfile #生成一個文件
root@e67af30200e3:/# ls /data/testdir/ #驗證文件存在
testfile
#在物理機中驗證文件是否存在
[root@docker-server1 _data]# cat testdir/testfile
xxoo
- 指定源目錄,推薦使用此方式,物理機可以將共享存儲掛載到本地,然後將本地掛載的目錄分配給容器使用,這樣容器掛掉之後也不影響數據的持久保存
[root@docker-server1 ~]# docker run -d --name nginx-test2 -v 源目錄:目標 鏡像名
[root@docker-server1 ~]# docker run -d --name nginx-test2 -v /data/testdir2/:/data nginx
ba02d63baff6637a15a6763e7c22a00f2ed56ab9c5438b352c4fbc9f691c1b13
- 容器中驗證:
#進入到容器並創建目錄生成文件
[root@docker-server1 ~]# ./docker.sh nginx-test2
root@ba02d63baff6:/# mkdir /data/testdir
root@ba02d63baff6:/# echo "ooxx" > /data/testdir/testfile
#在物理機進行驗證
[root@docker-server1 ~]# ls /data/testdir2/testdir/
testfile
[root@docker-server1 ~]# cat /data/testdir2/testdir/testfile
ooxx #文件已經存在
04.1.2、對掛載的目錄設置權限
[root@docker-server1 ~]# docker run -d --name nginx-test2 -v /data/testdir2/:/data:rw nginx #讀寫,默認就是讀寫掛載
[root@docker-server1 ~]# docker run -d --name nginx-test3 -v /data/testdir2/:/data:ro nginx #只讀
[root@docker-server1 ~]# ./docker.sh nginx-test3
root@70909a57c1f8:/# mkdir /data/testdir1 #進入到容器發現對該目錄沒有權限寫入
mkdir: cannot create directory ‘/data/testdir1‘: Read-only file system
04.1.3、單獨掛載文件
單獨掛載一個文件,比如是一個tomcat或nginx的配置文件要求所有容器都使用同一個配置文件的場景
[root@docker-server1 ~]# docker run -d --name nginx-test4 -v /usr/local/mysql/my.cnf:/etc/my.cnf:rw nginx #讀寫的方式掛載一個文件
[root@docker-server1 ~]# docker run -d --name nginx-test4 -v /usr/local/mysql/my.cnf:/etc/my.cnf:ro nginx #只讀的方式掛載一個文件
0b0d92f81165704a72d641670f216c3fffa81a5a530229380d17c04d2a35ff35
[root@docker-server1 ~]# ./docker.sh nginx-test4
root@0b0d92f81165:/# echo "xx" >> /etc/my.cnf #測試是否無法寫入
-bash: /etc/my.cnf: Read-only file system
04.1.4、管理數據卷
創建一個數據卷
[zhanghe@MacBook-Pro registry ]$ docker volume create my-data
my-data
查看所有的 數據卷
[zhanghe@MacBook-Pro registry ]$ docker volume ls
DRIVER VOLUME NAME
local my-data
刪除數據卷
[zhanghe@MacBook-Pro registry ]$ docker volume rm my-data
my-data
數據卷 是被設計用來持久化數據的,它的生命周期獨立於容器,Docker 不會在容器被刪除後自動刪除 數據卷,並且也不存在垃圾回收這樣的機制來處理沒有任何容器引用的 數據卷。如果需要在刪除容器的同時移除數據卷。可以在刪除容器的時候使用 docker rm -v 這個命令。
無主的數據卷可能會占據很多空間,要清理請使用以下命令
[zhanghe@MacBook-Pro registry ]$ docker volume prune
使用 --mount 標記可以指定掛載一個本地主機的目錄到容器中去。
[zhanghe@MacBook-Pro registry ]$ docker run -d -P --name web # -v /src/webapp:/opt/webapp --mount type=bind,source=/src/webapp,target=/opt/webapp training/webapp python app.py
上面的命令加載主機的 /src/webapp 目錄到容器的 /opt/webapp目錄。這個功能在進行測試的時候十分方便,比如用戶可以放置一些程序到本地目錄中,來查看容器是否正常工作。本地目錄的路徑必須是絕對路徑,以前使用 -v 參數時如果本地目錄不存在 Docker 會自動為你創建一個文件夾,現在使用 --mount 參數時如果本地目錄不存在,Docker 會報錯。
04.2、數據卷容器
04.2.1、容器數據共享
最大的功能是可以讓數據在多個docker容器之間共享,即可以讓A容器訪問B容器的內容,而B也可以訪問A容器的內容
- 啟動一個容器,並啟動另外一個容器掛載上一個容器的目錄
#先啟動一個容器,掛載物理機的一個目錄
[root@docker-server1 ~]# docker run -d --name nginx-test1 -v /data/testdir2/:/data:rw nginx
a108bd4a0fc09a3322e0cca07bbd4d0aa5d2249d399e860e2c7eaf0d63b8dd4e
#在啟動容器的時候可以使用--volumes-from參數訪問其他容器掛載的目錄
[root@docker-server1 ~]# docker run -d --name nginx-test3 --volumes-from nginx-test1 nginx
e506edcdfd71f64bd1ad67ce9be734184e54e408e758010a4f366d0b9de10536
- 在容器一個創建目錄並在第二個容器驗證
啟動容器
[root@docker-server1 ~]# ./docker.sh nginx-test1
root@a108bd4a0fc0:/# mkdir /data/testdir/test-volum
[root@docker-server1 ~]# ./docker.sh nginx-test3
root@e506edcdfd71:/# ls /data/testdir/
test-volume testfile #已經可以看到test-volume目錄了
關閉第一個容器,然後在第二個容器驗證數據是否可以訪問之前的目錄
[root@docker-server1 ~]# docker stop nginx-test1 #關閉容器1
nginx-test1
[root@docker-server1 ~]# ./docker.sh nginx-test3
root@e506edcdfd71:/# mkdir /data/testdir/test-volume1
#可以發現,即使將之前的容器關閉也不影響其他的容器訪問其目錄數據,因為容器是通過掛載訪問數據的
數據卷容器可以作為共享的方式為其他容器提供文件共享,類似於NFS共享,可以在生產中啟動一個實例掛載本地的目錄,然後其他的容器分別掛載此容器的目錄,即可保證各容器之間的數據一致性。
04.2.2、批量管理容器
- 批量關閉容器與刪除,威力巨大、效果顯著,慎用
[root@docker-server1 ~]# docker kill $(docker ps -a -q)
590d65e68d35
9a104c2f39ac
c6decbad5d08
[root@docker-server1 ~]# docker rm -f $(docker ps -a -q)
9d811ed2c371
0b0d92f81165
70909a57c1f8
Docker系列:04.數據共享與持久化