docker入门(4)--数据卷管理

2018-10-29  本文已影响0人  随意的ID

任何有意义的应用都会产生或者使用一些数据。而容器本身是无状态的。我们使用数据卷(volumes)来解决这个问题。数据卷允许容器使用,产生和修改数据。数据卷比容器拥有更高等级的生命周期,当使用volume的容器结束时,volume依然存在。

1. 创建和挂载数据卷

1.1 修改容器内数据

在正式开始介绍数据卷之前,我们先看看直接在容器内进行数据修改操作会发生什么。
在容器内新增一个文件:

docker container run --name demo \
    alpine /bin/sh -c 'echo "This is a test" > sample.txt'

容器与基础镜像进行比较:

docker container diff demo

结果类似如下:

A /sample.txt

当停止并移除这个容器后,你新建的sample.txt文件也会随之删除,再也无法继续使用。

1.2 创建数据卷

如下命令创建一个名为my-data的数据卷:
docker volume create my-data
默认的数据卷驱动称之为本地驱动,它将数据存储在本机的文件系统上。如果你需要了解数据卷的详细信息,可使用docker volume inspect命令进行核查。
docker volume inspect my-data
得到类似如下结果:

[
    {
        "CreatedAt": "2018-10-29T13:58:22+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-data/_data",
        "Name": "my-data",
        "Options": {},
        "Scope": "local"
    }
]

tips:docker还支持以插件形式使用的,第三方的一些数据卷驱动,例如:云存储,NFS,SDN(软件定义网络)存储。只需要在创建数据卷时,使用--driver参数进行指定即可。

1.3 挂载数据卷

当我们创建了数据卷之后,就可以挂载使用它了。

docker container run --name test -it \
    > -v my-data:/data alpine /bin/sh

启动并进入容器后,执行如下命令,在容器内新建文件:

/ # cd /data
/data # echo "some data" > data.txt
/data # echo "some more data" > data1.txt
/data # exit

回到主机,我们在/var/lib/docker/volumes/my-data/_data/目录下,可以看到:

[root@node2 ~]# ll /var/lib/docker/volumes/my-data/_data/
total 8
-rw-r--r-- 1 root root 15 Oct 29 14:13 data1.txt
-rw-r--r-- 1 root root 10 Oct 29 14:13 data.txt
[root@node2 ~]# cat /var/lib/docker/volumes/my-data/_data/data.txt 
some data
[root@node2 ~]# cat /var/lib/docker/volumes/my-data/_data/data1.txt 
some more data

接下来,我们直接在主机的数据卷目录下创建文件,然后新启动一个容器,挂载这个数据卷,看看是什么效果。

[root@node2 ~]# cd /var/lib/docker/volumes/my-data/_data/
[root@node2 _data]# echo "This file we create on the host" > host_data.txt
[root@node2 _data]# docker container rm test 
test
[root@node2 _data]# docker container run --name test2 -it \
> -v my-data:/app/data \
> centos:7 /bin/bash
Unable to find image 'centos:7' locally
7: Pulling from library/centos
aeb7866da422: Pull complete 
Digest: sha256:67dad89757a55bfdfabec8abd0e22f8c7c12a1856514726470228063ed86593b
Status: Downloaded newer image for centos:7
[root@9015fe11c4dd /]# ls /app/data
data.txt  data1.txt  host_data.txt
[root@9015fe11c4dd /]# cat /app/data/host_data.txt 
This file we create on the host

1.4 删除数据卷

我们可以使用docker volume rm来删除数据卷。特别提示:由于该操作是不可逆的,当你确认数据卷已经进行了备份,或者该数据卷确实没有其他用途的时候,你可以进行删除操作。但是,如果该数据卷如果还在使用中,是无法进行删除的。

[root@node2 _data]# docker volume rm my-data 
Error response from daemon: remove my-data: volume is in use - [9015fe11c4dd6450b2587e5b36979b64796541e7d67656003d8decae1fcc735e]
[root@node2 _data]# docker container ls -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                     PORTS                  NAMES
9015fe11c4dd        centos:7            "/bin/bash"              8 minutes ago       Exited (0) 4 minutes ago                          test2
78a0c2a1ac94        alpine              "/bin/sh"                3 days ago          Exited (0) 3 days ago                             sample
ce3d8b9082c5        alpine              "/bin/sh"                3 days ago          Exited (0) 3 days ago                             upbeat_kirch
48a55ac2ee94        nginx:alpine        "nginx -g 'daemon of…"   3 days ago          Up 3 days                  0.0.0.0:8080->80/tcp   nginx-test
0f8cf054c73d        alpine              "echo 'hello world'"     3 days ago          Exited (0) 3 days ago                             angry_colden
f5ed73fec895        hello-world         "/hello"                 3 days ago          Exited (0) 3 days ago                             dreamy_leakey
[root@node2 _data]# docker container rm 9015fe11c4dd
9015fe11c4dd
[root@node2 _data]# docker volume rm my-data 
my-data

2. 在容器之间分享数据

有些时候,容器之间是需要进行数据交互的。有可能A容器产生的数据,将用于给B容器进行读取使用,但为了避免冲突(同时对文件的修改),我们可以在挂载数据卷的时候设置一些读写权限。

[root@node2 ~]# docker volume create shared-data
shared-data
# 创建一个写文件的容器
[root@node2 ~]# docker container run --name writer -it \
> -v shared-data:/data \
> alpine /bin/sh
/ # cd /data
/data # touch data-from-writer.txt
/data # ls
data-from-writer.txt
# 创建一个只能读的容器,并挂载shared-data数据卷
[root@node2 ~]# docker container run --name only-reader -it \
> -v shared-data:/data:ro \
> centos:7 /bin/bash
[root@cf058c0af6af /]# cd /data/
[root@cf058c0af6af data]# touch data.txt
touch: cannot touch 'data.txt': Read-only file system

3. 使用主机目录进行挂载

除了数据卷,我们还可以将主机上的某个目录直接挂载到容器内,如下:

docker container run -d -v /my-web:/usr/share/nginx/html -p 8080:80 nginx:alpine

4. 在Dockerfile中定义数据卷

对于一些应用,例如数据库,我们肯定是需要进行数据持久化的,但是面对不同的使用者和不同的使用环境,我们的官方镜像是如何在面对不同环境时,主动的去定义一个数据卷呢?答案是:在Dockerfile中就定义好数据卷,这样生成的镜像在启动时,就会自动的创建数据卷。

# 列出目前已有的volume
[root@node2 ~]# docker volume ls
DRIVER              VOLUME NAME
local               shared-data
# 创建一个mongo容器
[root@node2 ~]# docker container run -d --name my-mongo mongo:3.7
e65ac72b9c3fc7abdcc05121b55c87543baccc3b27bf17be6ad0ec1212211141
# 查看自动添加的volume
[root@node2 ~]# docker volume ls
DRIVER              VOLUME NAME
local               065a116f6ef50622aa3e1f674f81cc61d13e4618b6f726b5fd77f4813fcc5e84
local               10242f5b75f1ba88e1e2abdbb2cc874887f4181353ea62ca6f2c6735c32b0e7b
local               shared-data

我们也可以使用docker image inspect命令来审查镜像的数据卷相关配置。

[root@node2 ~]# docker image inspect \
> --format='{{json .ContainerConfig.Volumes}}' \
> mongo:3.7 | jq
{
  "/data/configdb": {},
  "/data/db": {}
}

上面的结果显示,mongo:3.7这个image会创建两个volume。
我们也可以通过docker container inspect命令来审查当前运行容器的数据卷挂载情况。

[root@node2 ~]# docker container inspect --format '{{json .Mounts}}' my-mongo | jq
[
  {
    "Type": "volume",
    "Name": "065a116f6ef50622aa3e1f674f81cc61d13e4618b6f726b5fd77f4813fcc5e84",
    "Source": "/var/lib/docker/volumes/065a116f6ef50622aa3e1f674f81cc61d13e4618b6f726b5fd77f4813fcc5e84/_data",
    "Destination": "/data/configdb",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  },
  {
    "Type": "volume",
    "Name": "10242f5b75f1ba88e1e2abdbb2cc874887f4181353ea62ca6f2c6735c32b0e7b",
    "Source": "/var/lib/docker/volumes/10242f5b75f1ba88e1e2abdbb2cc874887f4181353ea62ca6f2c6735c32b0e7b/_data",
    "Destination": "/data/db",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

5. 关于使用volume还是bind mounts(本机目录)的建议

首先请参考这几篇官方文章:
Manage data in Docker
Use volumes
Use bind mounts
以下内容为谷歌翻译:

卷的好处:
绑定挂载的好处:

通常,您应该尽可能使用卷。绑定适用于以下类型的用例:

6. 关于使用-v参数还是--mount参数的建议

docker新用户,我们建议使用--mount,但是这个参数只能在docker 17.06版本以后才可以使用。
--mount参数使用如下:

$ docker service create \
     --mount 'type=volume,src=<VOLUME-NAME>,dst=<CONTAINER-PATH>,volume-driver=local,volume-opt=type=nfs,volume-opt=device=<nfs-server>:<nfs-path>,"volume-opt=o=addr=<nfs-address>,vers=4,soft,timeo=180,bg,tcp,rw"'
    --name myservice \
    <IMAGE>

--mount与-v的区别:

As opposed to bind mounts, all options for volumes are available for both --mount and -v flags.
When using volumes with services, only --mount is supported.

上一篇下一篇

猜你喜欢

热点阅读