docker数据卷

1.COW与数据卷

1.1 cow

Docker镜像由多个只读层叠加而成,容器启动时docker会加载只读镜像层并在镜像栈顶部添加一个读写层。而容器需要修改一个文件时,该文件将会从只读层复制到读写层并将其修改,而只读层的文件不会改变同时会被读写层修改的相应文件隐藏,这就是“写时复制(COW)”机制。

1.2 数据卷

存储卷就是将宿主机本地文件系统中的某个目录直接与容器内部文件系统上的某一目录建立绑定关系。这就意味着,当我们在容器中的这个目录下写入数据时,容器会将其内容直接写入到宿主机上的绑定目录。在宿主机上的这个与容器形成绑定关系的目录被称作存储卷。

数据卷优势

容器运行时将有效数据保存在存储卷中,那么当容器关闭甚至删除时,只要不删除数据卷,就不用当心数据会随着容器而丢失,从而实现数据持久化。同时,还可以部署nfs文件共享,实现容器的数据脱离宿主机的限制。

数据卷分类

Docker有两种类型的卷,每种类型都在容器中存在一个挂载点,但其在宿主机上的位置有所不同:

  • 1.Bind mount volume
##自定义绑定的目录
docker run -it --name CONTAINER_NAME -v HOSTDIR:VOLUMEDIR IMAGE_NAME
    1. Docker-managed volume
##绑定在宿主机固定目录上/var/lib/docker/volumes/
docker run -it --name CONTAINER_NAME -v VOLUMEDIR IMAGE_NAME

2.容器数据管理

容器中管理数据主要有两种方式:数据卷、数据卷容器

[root@vm1 volumes]# docker run --help 
.........................................
-v, --volume list                    Bind mount a volume
      --volume-driver string           Optional volume driver for the container
      --volumes-from list              Mount volumes from the specified container(s)

2.1 数据卷

创建docker管理卷

  • Docker-managed volume
  • 运行容器并创建管理卷、向管理卷中写入数据
## -v {容器内数据卷目录} 若不存在就自动创建
[root@vm1 ~]# docker run -it -p 8080:80 --name web -v /webapp nginx /bin/bash
root@30be2cb45f1c:/# ls
bin   dev		   docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc			 lib   media  opt  root  sbin  sys  usr  webapp
root@30be2cb45f1c:/# cd webapp/
root@30be2cb45f1c:/webapp# ls
root@30be2cb45f1c:/webapp# cat > index.html <<EOF
> hello nignx!
> EOF
root@30be2cb45f1c:/webapp# ls
index.html
  • 查找管理卷对应在宿主机上的目录
[root@vm1 volumes]# docker ps 
CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                  NAMES
30be2cb45f1c   nginx     "/docker-entrypoint.…"   5 minutes ago   Up 5 minutes   0.0.0.0:8080->80/tcp   web
[root@vm1 volumes]# docker inspect web
...........................................
 "Mounts": [
            {
                "Type": "volume",
                "Name": "197cb6d106f751c4ebc7ee09d4f9d72a4a259e2ed208d3b6766b57d60ed1485b",
                "Source": "/var/lib/docker/volumes/197cb6d106f751c4ebc7ee09d4f9d72a4a259e2ed208d3b6766b57d60ed1485b/_data",
                "Destination": "/webapp",
...........................................
[root@vm1 volumes]# cd /var/lib/docker/volumes/
[root@vm1 volumes]# ls
197cb6d106f751c4ebc7ee09d4f9d72a4a259e2ed208d3b6766b57d60ed1485b  c3836c6a68d5fcb5cee3b6449cf54eb5449eb0a605dae2c17d44397dd692ecae
backingFsBlockDev                                                 metadata.db
[root@vm1 volumes]# cd 197cb6d106f751c4ebc7ee09d4f9d72a4a259e2ed208d3b6766b57d60ed1485b/
[root@vm1 197cb6d106f751c4ebc7ee09d4f9d72a4a259e2ed208d3b6766b57d60ed1485b]# ls
_data
[root@vm1 197cb6d106f751c4ebc7ee09d4f9d72a4a259e2ed208d3b6766b57d60ed1485b]# cd _data/
[root@vm1 _data]# ls
index.html
[root@vm1 _data]# cat index.html 
hello nignx!
  • 在宿主机上修改该文件
[root@vm1 _data]# cat >> index.html <<EOF
> hello world!
> EOF
[root@vm1 _data]# cat index.html 
hello nignx!
hello world!
  • 在容器中查看是否修改
root@30be2cb45f1c:/webapp# cat index.html 
hello nignx!
hello world!
  • 删除容器查看数据是否丢失
[root@vm1 ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS     NAMES
30be2cb45f1c   nginx     "/docker-entrypoint.…"   15 minutes ago   Exited (0) 20 seconds ago             web
9f2364a14459   busybox   "/bin/sh"                35 minutes ago   Exited (0) 18 minutes ago             test
[root@vm1 ~]# docker rm web test
web
test
[root@vm1 _data]# pwd
/var/lib/docker/volumes/197cb6d106f751c4ebc7ee09d4f9d72a4a259e2ed208d3b6766b57d60ed1485b/_data
[root@vm1 _data]# ls
index.html
[root@vm1 _data]# cat index.html 
hello nignx!
hello world!

创建绑定挂载卷

  • Bind mount volume
  • 运行容器并创建绑定挂载卷
##/var/www/html:/webapp[:ro/rw] 默认为rw
[root@vm1 ~]# docker run -d -p 8080:80 --name web2 -v /var/www/html:/webapp nginx
61be8f13e0a5f83a0c3b15cdb58c935e7f12ffd7a27a99e8a5548e8e5a120b8b
[root@vm1 ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                  NAMES
61be8f13e0a5   nginx     "/docker-entrypoint.…"   19 seconds ago   Up 16 seconds   0.0.0.0:8080->80/tcp   web2
[root@vm1 ~]# 
  • 在宿主机上绑定目录创建文件
[root@vm1 ~]# cd /var/www/html/
[root@vm1 html]# ls
[root@vm1 html]# cat > index.html<<EOF
> hello! web2
> EOF
[root@vm1 html]# ls
index.html
[root@vm1 html]# cat index.html 
hello! web2
  • 进入容器查看目录
[root@vm1 html]# docker exec -it web2 /bin/bash
root@61be8f13e0a5:/# ls
bin   dev		   docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc			 lib   media  opt  root  sbin  sys  usr  webapp
root@61be8f13e0a5:/# cd webapp/
root@61be8f13e0a5:/webapp# ls
index.html
root@61be8f13e0a5:/webapp# cat index.html 
hello! web2
  • 在容器中修改该文件
root@61be8f13e0a5:/webapp# ls
index.html
root@61be8f13e0a5:/webapp# cat >> index.html <<EOF
> !!!!!!!!!!!!
> EOF
root@61be8f13e0a5:/webapp# ls
index.html
root@61be8f13e0a5:/webapp# cat index.html 
hello! web2
!!!!!!!!!!!!
  • 宿主机查看是修改
[root@vm1 html]# pwd
/var/www/html
[root@vm1 html]# ls
index.html
[root@vm1 html]# cat index.html 
hello! web2
!!!!!!!!!!!!
  • 挂载本地主机文件作为数据卷
[root@vm1 ~]# docker run -it --rm -v ~/.bash_history:/.bash_history ubuntu /bin/bash
root@4332349a5c44:/# tail .bash_history 
rm -f containerd.sock
rm -f containerd.sock.ttrpc 
ls
pwd
ip a
ls
cd ../
ls
cd containerd/
ls

如果直接挂载一个文件到容器,使用文件编辑工具,包括vi或者sed去修改文件内容的时候,可能会造成inode的改变,这样将会导致错误。所以推荐的方式是直接挂载文件所在的目录。

2.2 数据卷容器

如果用户需要在容器之间共享一些持续更新的数据,最简单的方式是使用数据卷容器。

  • 创建数据卷容器
[root@vm1 ~]# docker run  -itd --name dbcontainer -v /dbdata busybox 
9acccd9ea148ce2478c89034bfd7e0baf36af6588e5c68d0600b751c48e89ce6
[root@vm1 ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS         PORTS     NAMES
9acccd9ea148   busybox   "sh"      13 seconds ago   Up 7 seconds             dbcontainer
  • 创建新容器,从数据卷容器中挂载数据卷(--volumes-from参数所挂载数据卷的容器自身并不需要保持在运行状态)
[root@vm1 ~]# docker run -itd --name db1 --volumes-from dbcontainer busybox
94884555f8da33c845221828e5b5622f9c5f1f1cefd8619ee228641a254c31fd
[root@vm1 ~]# docker run -itd --name db2 --volumes-from dbcontainer busybox
cf10f10036f88059d0773f8d9034dd86c5eb2ca41ae87d5d10f0f8f144b707ce
[root@vm1 ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
cf10f10036f8   busybox   "sh"      5 seconds ago    Up 2 seconds              db2
94884555f8da   busybox   "sh"      14 seconds ago   Up 11 seconds             db1
9acccd9ea148   busybox   "sh"      7 minutes ago    Up 6 minutes              dbcontainer

  • 在dbcontainer的数据卷创建文件
[root@vm1 ~]# docker exec -it dbcontainer /bin/sh
/ # ls
bin     dbdata  dev     etc     home    proc    root    sys     tmp     usr     var
/ # cd dbdata/
/dbdata # touch test.txt
/dbdata # ls
test.txt

  • 在db1,db2上查看
[root@vm1 ~]# docker exec -it db1 /bin/sh
/ # ls
bin     dbdata  dev     etc     home    proc    root    sys     tmp     usr     var
/ # cd dbdata/
/dbdata # ls
test.txt
[root@vm1 ~]# docker exec -it db2 /bin/sh
/ # ls
bin     dbdata  dev     etc     home    proc    root    sys     tmp     usr     var
/ # cd dbdata/
/dbdata # ls
test.txt
  • 在db2上修改文件,其他容器上查看
[root@vm1 ~]# docker exec -it db2 /bin/sh
/ # ls
bin     dbdata  dev     etc     home    proc    root    sys     tmp     usr     var
/ # cd dbdata/
/dbdata # ls
test.txt
/dbdata # cat > test.txt <<EOF 
> this is a test !
> EOF
/dbdata # ls
test.txt
/dbdata # cat test.txt 
this is a test !
[root@vm1 ~]# docker exec -it db1 /bin/sh
/ # cat /dbdata/test.txt 
this is a test !
/ # exit
[root@vm1 ~]# docker exec -it dbcontainer /bin/sh
/ # cat /dbdata/test.txt 
this is a test !

  • 宿主机上查看绑定的目录
[root@vm1 ~]# docker inspect dbcontainer
........................
"Mounts": [
            {
                "Type": "volume",
                "Name": "05316f720262f148b63277eb6efc1364c9ad4980ac7d50b9d699e57c34925fa4",
                "Source": "/var/lib/docker/volumes/05316f720262f148b63277eb6efc1364c9ad4980ac7d50b9d699e57c34925fa4/_data",
                "Destination": "/dbdata",
[root@vm1 ~]# cd /var/lib/docker/volumes/05316f720262f148b63277eb6efc1364c9ad4980ac7d50b9d699e57c34925fa4/
[root@vm1 05316f720262f148b63277eb6efc1364c9ad4980ac7d50b9d699e57c34925fa4]# ls
_data
[root@vm1 05316f720262f148b63277eb6efc1364c9ad4980ac7d50b9d699e57c34925fa4]# cd _data/
[root@vm1 _data]# ls
test.txt
[root@vm1 _data]# cat test.txt 
this is a test !
  • 删除数据卷:docker rm -v 容器 当与本机绑定的目录相关的所有容器删除时才数据卷才会删
[root@vm1 _data]# ls
test.txt
[root@vm1 _data]# cat test.txt 
this is a test !
[root@vm1 ~]# docker rm -v -f db1
db1
[root@vm1 ~]# docker rm -v -f db2
db2
[root@vm1 ~]# docker rm -v -f  dbcontainer
dbcontainer
[root@vm1 _data]# pwd
/var/lib/docker/volumes/05316f720262f148b63277eb6efc1364c9ad4980ac7d50b9d699e57c34925fa4/_data
[root@vm1 _data]# ls
[root@vm1 _data]# 

2.3 数据卷容器迁移数据

可以利用数据卷容器对其中的数据卷进行备份、恢复,以实现数据的迁移。

  • 创建数据卷容器,并在数据卷中写入数据
[root@vm1 _data]# docker run -itd --name dbcontainer -v /dbdata busybox
1efa3b9764361ea430ea2c7ae5d7d9894f2098b0041f0998fe23585a32e7bfdb
[root@vm1 _data]# docker ps 
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS         PORTS     NAMES
1efa3b976436   busybox   "sh"      10 seconds ago   Up 8 seconds             dbcontainer
[root@vm1 ~]# docker exec -it dbcontainer /bin/sh
/ # ls
bin     dbdata  dev     etc     home    proc    root    sys     tmp     usr     var
/ # cd /dbdata/
/dbdata # ls
/dbdata # 
/dbdata # mkdir test 
/dbdata # cd test 
/dbdata/test # ls
/dbdata/test # touch a abc 123 456 
/dbdata/test # ls
123  456  a    abc
/dbdata/test # cd ../
/dbdata # ls
test
/dbdata # touch index.html 
/dbdata # ls
index.html  test

备份

  • 备份dbcontainer数据卷容器中的dbdata数据内容
[root@vm1 _data]# docker run --name work --volumes-from dbcontainer -v /opt:/backup busybox tar cvf /backup/backup.tar /dbdata
tar: removing leading '/' from member names
dbdata/
dbdata/test/
dbdata/test/a
dbdata/test/abc
dbdata/test/123
dbdata/test/456
dbdata/index.html
[root@vm1 _data]# cd /opt/
[root@vm1 opt]# ls
backup.tar  containerd

恢复

  • 恢复数据到一个容器
  • 创建数据卷容器dbcontainer2
[root@vm1 containerd]# docker run -it --name dbcontainer2 -v /dbdata busybox /bin/sh
/ # ls
bin     dbdata  dev     etc     home    proc    root    sys     tmp     usr     var
/ # cd dbdata/
/dbdata # ls
/dbdata # 

  • 创建新的容器挂载dbcontainer2,绑定备份文件所在目录和容器目录,并解压至容器/dbdata下,即dbcontainer2的/dbdata下
[root@vm1 opt]# docker run --name work2 --volumes-from dbcontainer2 -v /opt:/backup busybox tar xvf /backup/backup.tar -C /dbdata
dbdata/
dbdata/test/
dbdata/test/a
dbdata/test/abc
dbdata/test/123
dbdata/test/456
dbdata/index.html
  • 查看在dbcontainer2中是否恢复
[root@vm1 containerd]# docker exec -it dbcontainer2 /bin/sh
/ # ls
bin     dbdata  dev     etc     home    proc    root    sys     tmp     usr     var
/ # cd dbdata/
/dbdata # ls
dbdata
/dbdata # cd dbdata/
/dbdata/dbdata # ls
index.html  test
/dbdata/dbdata # cd test/
/dbdata/dbdata/test # ls
123  456  a    abc
posted @ 2021-01-10 19:53  小芃总  阅读(158)  评论(0编辑  收藏  举报