Docker数据管理

用户在使用 Docker 的过程中,往往需要能查看容器内产生的数据,或者需要把容器内的数据进行备份,甚至多个容器之间进行数据共享,所以了解容器的数据管理操作还是必要的。

容器中操作数据主要有两种方式:

  • 数据卷(Data Volume)
  • 数据卷容器(Data Volume Containers)

容器是只有运行状态的,也就是容器的生命周期结束后,所有数据都会重置,如果想在其中保存数据而不影响镜像,一般就用数据卷。

volume 并不会跟随 commit 打包而提交到一个新的镜像上,官方文档给的说法是

The commit operation will not include any data contained in volumes mounted inside the container.
It can be useful to commit a container’s file changes or settings into a new image.

 

 
Docker 中数据持久化的方式有三种
volume
是由docker默认及推荐的挂载方式,volume由docker直接管理,同一个volume可以共享给多个容器使用,volume和容器的生命周期完全独立,容器删除时volume仍然存在,除非使用docker volume相应命令删除volume;缺点是volume在宿主机上比较难定位,在宿主机上直接操作volume比较困难。
bind mount
是直接将宿主机文件系统上的文件路径映射到容器中,两边双向同步,显而易见,有缺点也有优点,优点是可以直接访问,也可以被别的程序使用,比如我们打包一个本地应用到本地/target路径,我们就可以把这个路径使用bind mount的方式挂在到依赖他的应用的docker容器中,这样本地应用打包后,docker里的数据卷也会同时更新;缺点也是显而易见的,因为你可以把任何文件路径使用bind mount的方式绑定到容器中,这样有可能一些安全问题,比如把宿主机的系统文件绑定到容器中。
tmpfs
这种方式是使用宿主机的内存作为存储,不会写到宿主机的文件系统中,和前两种区别较大。 

 

 

创建一个数据卷

在用 docker run 命令的时候,使用 -v 可以在容器内创建一个数据卷,多次使用 -v 可以使用多个数据卷

# 使用 training/webapp 镜像创建容器,并且挂载数据卷到 /webapp 目录
$ sudo docker run -d -p --name web -v /webapp training/webapp python app.py

如果是需要挂载一个主机目录到容器的数据,则如下,将主机的 /src/webapp 挂载到容器内的 /opt/webapp 目录 :

$ sudo docker run -d -p --name web -v /src/webapp:/opt/webapp training/webapp python app.py

数据卷还能设置其读写权限(rw),ro 标识的是指定只读,这样在容器挂载后此数据卷的数据就无法修改了

$ sudo docker run -d -p --name web -v /src/webapp:/opt/webapp:ro training/webapp python app.py

在宿主机中查看容器挂载的 volume,其实数据卷的原理没有那么复杂,也是寄托主机的文件系统来实现的。

 

比如下面启动一个mysql的容器,在这里会说明两种不同数据卷类型的区别:volume,bindmount

## 默认的 volume
$ docker run -d --name mysql-local1 -e MYSQL_ROOT_PASSWORD=root mysql:5.7
## 这样子的挂载会默认存在 docker 的 volume 目录下
[vagrant@docker-node3 ~]$ sudo ls /var/lib/docker/volumes
c5020bd3e7253cd1fdfce10243424074846642d6db933bf66a911f6bdd0858a8  metadata.db

## 如果你不想用一个一大串的名字,还可以单独命名
## 这里的 mysql 就是 volume 的名字
## docker volume ls 下的名字
$ docker run -d -v mysql:/var/lib/mysql --name mysql-local1 -e MYSQL_ROOT_PASSWORD=root mysql:5.7

## 如果使用 bind-mount 的方式来挂载,也就是本地宿主机的目录,而不是docker的volume目录
$ docker run -v /var/own/mysqldata:/var/lib/mysql --name mysqlnew -d mysql -e MYSQL_ROOT_PASSWORD=root mysql:5.7

 

查看容器,和其运行配置

[vagrant@docker-node3 ~]$ docker container ls
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
13bcca305b36        mysql:5.7           "docker-entrypoint.s…"   37 minutes ago      Up 37 minutes       3306/tcp, 33060/tcp   mysql-local1
[vagrant@docker-node3 ~]$ docker inspect 13bcca305b36
====
"Mounts": [
            {
                "Type": "volume",
                "Name": "c5020bd3e7253cd1fdfce10243424074846642d6db933bf66a911f6bdd0858a8",
                "Source": "/var/lib/docker/volumes/c5020bd3e7253cd1fdfce10243424074846642d6db933bf66a911f6bdd0858a8/_data",
                "Destination": "/var/lib/mysql",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
====

查看这个 mysql 镜像起的容器所关联的数据卷所在的目录

[vagrant@docker-node3 ~]$ sudo ls /var/lib/docker/volumes/c5020bd3e7253cd1fdfce10243424074846642d6db933bf66a911f6bdd0858a8/_data
auto.cnf    ca.pem         client-key.pem  ib_logfile0  ibdata1  performance_schema  public_key.pem    server-key.pem
ca-key.pem  client-cert.pem  ib_buffer_pool  ib_logfile1  mysql    private_key.pem     server-cert.pem    sys

可以看到具体的某个容器的数据卷是保存在 docker 的如下目录下的:/var/lib/docker/volumes/XXX

 

 

开发环境 docker+bindmount 打造自己的开发环境

在数据卷中可以将代码挂载在容器内,拿开发一个 flask 的 python web 应用,可以将代码挂载在数据卷中,在宿主机进行开发,然后容器内运行

比如当前目录,有 flask 的路由的相关控制器逻辑:

./dockerLib/flask-skeleton/
|-- __init__.py
|-- base.py
|-- test_config.py
|-- test_main.py
`-- test_user.py

test_user.py 内是路由相关的逻辑

 

 启动一个容器将当前目录挂载进去

$ docker run -d -p 80:5000 -v $(pwd):/skeleton --name flask blackbinbin/flask-skeleton

那么就可以在外主机目录下的文件进行编辑,在容器内进行调试了。

 

posted @ 2022-01-23 17:36  Blackbinbin  阅读(41)  评论(0编辑  收藏  举报