默认情况下,容器会随着用户删除而消失,包括容器里面的数据。如果我们要对容器里面的数据进行长久保存,就不得不引用存储卷的概念。

在容器中管理数据持久化主要有两种方式:
1、数据卷(data volumes)
2、挂载目录(Bind volumes)

数据卷

数据卷是一个可供一个或多个容器使用的共同目录,它提供很多有用的特性:
1、数据卷可以在容器之间共享和重用;
2、对数据卷的修改会立马生效;
3、对数据卷的更新不会影响镜像;
4、数据卷默认会一直存在,即使容器被删除;

注意:数据卷的使用类似于Linux下对目录进行mount,镜像中被指定的挂载点中的文件会被隐藏,显示的是我们挂载的数据卷。

数据卷的常用命令是docker volume命令,常规用法如下:

  1. # docker volume --help
  2. Usage: docker volume COMMAND
  3. Manage volumes
  4. Commands:
  5. create Create a volume
  6. inspect Display detailed information on one or more volumes
  7. ls List volumes
  8. prune Remove all unused local volumes
  9. rm Remove one or more volumes
  10. Run 'docker volume COMMAND --help' for more information on a command.

创建数据卷:

docker volume create my_volume

查看数据卷:

# docker volume ls
DRIVER              VOLUME NAME
local               7a9cbb48630c66180ba226974aa9307a502ce4c99648be48e1a0cfcbe4573854
local               861cb1d1c824570a426a6b2599357b6d66818cd98a36010857cb7d753312d11d
local               my_volume
local               mydata
local               nginx_volume
local               vol_simple
local               wpdata

查看数据卷的详细信息:

# docker volume inspect my_volume
[
    {
        "CreatedAt": "2019-07-28T13:01:27+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my_volume/_data",
        "Name": "my_volume",
        "Options": {},
        "Scope": "local"
    }
]

启动一个容器挂载数据卷,挂载数据卷的方法有两种:
1、用-v或者—volume;

# docker run -it --rm --name my_app -v my_volume:/data/apps busybox

2、用—mount;

# docker run -it --rm --name my_app --mount source=my_volume,target=/data/apps busybox

容器启动后可以查看容器信息,就可以看到具体的挂载信息:

# docker inspect my_app
......
"Mounts": [
            {
                "Type": "volume",
                "Name": "my_volume",
                "Source": "/var/lib/docker/volumes/my_volume/_data",
                "Destination": "/data/apps",
                "Driver": "local",
                "Mode": "z",
                "RW": true,
                "Propagation": ""
            }
        ],
......

删除数据卷:

# docker volume rm my_volume

数据卷是用来持久化容器数据的,它独立于容器的生命周期,如果需要删除容器的同时也移除数据卷,可以使用docker rm -v命令。

如果要清理一些无主的数据卷,可以使用下面命令:

# docker volume prune

挂载目录

挂载主机目录和挂载数据卷的方式一样,只是在指定需要挂载的目录是一个全路径目录,比如:

# docker run -it --rm --name my_app -v /tmp/my_app:/data/apps busybox
# docker run -it --rm --name my_app --mount type=bind,source=/tmp/my_app,target=/data/apps busybox

从上面知道用-v和—mount都可以进行挂载。如果使用-v来挂载目录,如果本地/tmp/my_app存在,则直接将这个目录挂载到容器上,里面如果有文件等,就可以在容器中直接进行查看。如果本地没有这个目录,则在启动容器的过程中自动创建这个目录。如果使用—mount来挂载目录,如果本地目录不存在,就会报错,比如:

# docker run -it --rm --name my_app --mount type=bind,source=/tmp/my_app/web/data,target=/data/apps busybox
docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /tmp/my_app/web/data.
See 'docker run --help'.

默认挂载到容器中的目录,docker对其是有读写权限的,用户可以增加readonly参数使其只有只读权限。

# docker run -it --rm --name my_app --mount type=bind,source=/tmp/my_app,target=/data/apps,readonly busybox
/ # cd /data/apps/
/data/apps # ls
/data/apps # touch 1.txt
touch: 1.txt: Read-only file system

不仅可以挂载目录,还可以挂载单个文件,如下:

# docker run -it --rm --name my_app --mount type=bind,source=/$HOME/.bash_history,target=/data/apps/history busybox
# docker run -it --rm --name my_app -v /$HOME/.bash_history:/data/apps/history busybox

如果是跨主机使用,可以通过共享存储,比如NFS之类的。这样我们只要挂载NFS的目录,所有的读写操作其他主机也可见。

除了使用上面这两种挂载之外,还可以使用现有容器的挂载,通过—volumes-from命令就可以直接使用其他容器的挂载,比如:

# docker run -it --rm --name my_app -v /$HOME/.bash_history:/data/apps/history busybox
# docker run -it --rm --name new_app --volumes-from my_app busybox

这样,my_app和new_app使用的就是同一个挂载卷了。