Docker-3.Docker数据存储

Docker之三:Docker数据存储

Docker的镜像是分层设计的,底层是只读的,docker镜像在构建的时候利用了aufs文件系统的挂载原理添加了一层可读写的文件系统,用户写入的数据都保存在这一层当中.


如果要将写入的数据永久生效,需要将其提交为一个镜像然后通过这个镜像在启动实例,然后就会给这个启动的实例添加一层可读写的文件系统,以此类推,目前docker将数据存储分为两种方式,数据卷和数据容器卷,具体如下:

1.1:数据卷:

1.1.1:数据卷类似一个被挂载的目录。启动后的docker容器可以在这个目录进行读写操作,类似于远程挂载一个NFS共享

1
2
3
4
5
6
7
8
9
[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 tmpfs 68M 0 68M 0% /dev/shm

1.1.2:上面的data目录还有47G的空间,那个这个数据目录在物理机的位置在哪里?

1
2
3
4
5
6
[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"

1.1.3:在物理机创建目录验证容器当中是否可以访问并写入数据:

1
2
3
4
5
6
7
8
9
10
11
12
[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

1.2:指定源目录,推荐使用此方式,物理机可以将共享存储挂载到本地,然后将本地挂载的目录分配给容器使用,这样容器挂掉之后也不影响数据的持久保存:

1.2.1:命令如下:

1
2
3
[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

1.2.2:容器中验证:

1
2
3
4
5
6
7
8
9
#进入到容器并创建目录生成文件
[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 #文件已经存在

1.2.3:对挂载的目录设置权限:

1
2
3
4
5
[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

1.2.4:单独挂载一个文件,比如是一个tomcat或nginx的配置文件要求所有容器都使用同一个配置文件的场景:

~]# docker run -d --name nginx-test4 -vnginx #读写的方式挂载一个文件
1
2
3
4
5
[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

2:数据卷容器:

  • 最大的功能是可以让数据在多个docker容器之间共享,即可以让A容器访问B容器的内容,而B也可以访问A容器的内容:

    2.1:启动一个容器,并启动另外一个容器挂载上一个容器的目录:

    1
    2
    3
    4
    5
    [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

    2.2:在容器一个创建目录并在第二个容器验证:

    2.2.1:启动容器:

    1
    2
    3
    4
    5
    [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目录了

    2.2.2:关闭第一个容器,然后在第二个容器验证数据是否可以访问之前的目录:

    ~]# docker stop nginx-test1 #关闭容器1
    1
    2
    3
    4
    nginx-test1
    [root@docker-server1 ~]# ./docker.sh nginx-test3
    root@e506edcdfd71:/# mkdir /data/testdir/test-volume1
    #可以发现,即使将之前的容器关闭也不影响其他的容器访问其目录数据,因为容器是通过挂载访问数据的

    2.2.3:数据卷容器可以作为共享的方式为其他容器提供文件共享,类似于NFS共享,可以在生产中启动一个实例挂载本地的目录,然后其他的容器分别挂载此容器的目录,即可保证各容器之间的数据一致性。

    2.2.4:批量关闭容器与删除,威力巨大、效果显著,慎用:

    ~]# docker kill $(docker ps -a -q)
    1
    2
    3
    4
    5
    6
    7
    590d65e68d35
    9a104c2f39ac
    c6decbad5d08
    [root@docker-server1 ~]# docker rm -f $(docker ps -a -q)
    9d811ed2c371
    0b0d92f81165
    70909a57c1f8
0%