Docker系列:04.数据共享与持久化

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

猜你喜欢

转载自blog.51cto.com/zhang789/2153811
今日推荐