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
那么就可以在外主机目录下的文件进行编辑,在容器内进行调试了。