docker容器数据卷

Posted SmallForest

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了docker容器数据卷相关的知识,希望对你有一定的参考价值。

背景

将应用和运行环境打包成一个镜像
为了数据安全,数据不能放在容器中
数据需要持久化存储
卷技术说白了,将容器内目录挂载到Linux中的目录,文件同步的机制
卷的目的:为了做持久化和同步,容器间也可以实现数据共享

使用数据卷 方式一

docker run -it -v 宿主机目录:容器内目录 centos /bin/bash
启动之后可以使用
docker inspect 容器id
查看Mounts

  • 请手敲代码!
  • code
#执行挂载命令-v
➜  ~ docker run -it -d --name centos01  -v /Users/dada/Downloads/docker-centos/etc:/etc centos
6080c9748915bd8c64d2cc218ff3f3431a155fd360be60620184eb80ba6a6add

#查看运行中的容器列表
➜  ~ docker ps
CONTAINER ID   IMAGE        COMMAND             CREATED         STATUS         PORTS                                       NAMES
6080c9748915   centos       "/bin/bash"         3 seconds ago   Up 2 seconds                                               centos01

#进入容器
➜  ~ docker exec -it 6080c9748915 /bin/bash

#进入etc 创建文件并写入数据
bash-4.4# cd /etc/
bash-4.4# touch index.html & echo \'hi! smallForest\'>index.html

# ls一下
bash-4.4# ls
hostname  hosts  index.html  resolv.conf

# 退出容器
bash-4.4# exit

# 查看容器信息 inspect
➜  ~ docker inspect 6080c9748915
返回结果巨长,只写Mounts部分
"Mounts": [
            {
                "Type": "bind",
                "Source": "/Users/dada/Downloads/docker-centos/etc",
                "Destination": "/etc",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
# 回到宿主机目录/Users/dada/Downloads/docker-centos/etc。校验index.html是否存在,内容是否是\'hi! smallForest\'

容器停止宿主机修改文件重启后会同步吗?

  • 请手敲命令
  • code

    # 查看运行中的容器
    ➜  ~ docker ps
    CONTAINER ID   IMAGE        COMMAND             CREATED          STATUS          PORTS                                       NAMES
    6080c9748915   centos       "/bin/bash"         12 minutes ago   Up 12 minutes                                               centos01
    
    # 停止容器
    ➜  ~ docker stop 6080c9748915
    6080c9748915
    
    ➜  ~ docker ps
    CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
    
    #在宿主机中修改index.html追加一句话
    ➜  ~ vim /Users/dada/Downloads/docker-centos/etc/index.html
    
    ➜  ~ cat /Users/dada/Downloads/docker-centos/etc/index.html
    hi! smallForest
    update on MacOS
    
    #启动容器
    ➜  ~ docker start 6080c9748915
    6080c9748915
    
    #进入容器
    ➜  ~ docker exec -it 6080c9748915 /bin/bash 
    
    #进入配置目录
    bash-4.4# cd /etc/
    
    #查看index.html已经同步更新
    bash-4.4# cat index.html 
    hi! smallForest
    update on MacOS
    
  • 结论:容器停止宿主机修改文件重启后会同步

    挂载到宿主机目录之后删除容器,数据会删除吗?

    mysql数据同步 持久化问题。需要配置pwd

  • code
docker run -d -p 3306:3306 -v /Users/dada/Downloads/docker-centos/mysql/conf:/etc/mysql/conf.d -v /Users/dada/Downloads/docker-centos/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
Unable to find image \'mysql:5.7\' locally
5.7: Pulling from library/mysql
69692152171a: Already exists 
1651b0be3df3: Pull complete 
951da7386bc8: Pull complete 
0f86c95aa242: Pull complete 
37ba2d8bd4fe: Pull complete 
6d278bb05e94: Pull complete 
497efbd93a3e: Pull complete 
a023ae82eef5: Pull complete 
e76c35f20ee7: Pull complete 
e887524d2ef9: Pull complete 
ccb65627e1c3: Pull complete 
Digest: sha256:a682e3c78fc5bd941e9db080b4796c75f69a28a8cad65677c23f7a9f18ba21fa
Status: Downloaded newer image for mysql:5.7
bcc85b93643d2c1cb84f786eed080f55d346a8df15260327a673b8cd98224d14

# 使用密码123456连接Navicat 并创建一个数据库

# 删除容器
➜  ~ docker stop bcc85b93643d & docker rm bcc85b93643d

➜  ~ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

#回到宿主机目录/Users/dada/Downloads/docker-centos/mysql/data 查看数据库文件是否存在
  • 结论:挂载到宿主机目录之后删除容器,数据不会删除

    匿名挂载

    -v 容器内目录!不指定宿主机路径

  • code

    # 启动nginx容器,匿名挂载,-P表示自动指定端口
    ➜  ~ docker run -d -P --name nginx01 -v /etc/nginx nginx:latest
    8f2ea2ad93a0e3d98560c9f59e7d7f05a90375b909d7b265f14151e845256694
    
    # 查看容器详情
    ➜  ~ docker inspect 8f2ea2ad93a0
    #简略展示
    "Mounts": [
              {
                  "Type": "volume",
                  "Name": "f50a729cba7814d70f11dbb0862c5aefc1b076b142c84bc5133986cdc2a869ce",
                  "Source": "/var/lib/docker/volumes/f50a729cba7814d70f11dbb0862c5aefc1b076b142c84bc5133986cdc2a869ce/_data",
                  "Destination": "/etc/nginx",
                  "Driver": "local",
                  "Mode": "",
                  "RW": true,
                  "Propagation": ""
              }
          ],
    
    # 查看本地所有卷的列表
    ➜  ~ docker volume ls

    具名挂载

    给卷设置名字
    -v 卷名:容器内目录

  • code
# 创建nginx容器 具名挂载
➜  ~ docker run -d -P --name nginx03 -v juming-nginx:/etc/nginx nginx:latest
cae84c37d3f4278815fd7793b59b54250dfc65355d9748d30dcebe6bf0e1de2e

# 查看本地所有的卷
➜  ~ docker volume ls
DRIVER    VOLUME NAME
local     juming-nginx
local     portainer_data
local     user_cert

# 查看卷名“juming-nginx”的信息,Mountpoint就是宿主机存储文件位置
➜  ~ docker volume inspect juming-nginx
[
    {
        "CreatedAt": "2021-05-26T09:10:55Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/juming-nginx/_data",
        "Name": "juming-nginx",
        "Options": null,
        "Scope": "local"
    }
]
  • 具名挂载方式方便找卷

    区分匿名挂载,具名挂载,指定宿主路径挂载

  • -v 容器内路径
  • -v 卷名:容器内路径
  • -v /宿主机路径:容器内路径

扩展知识:
-v juming-nginx:/etc/nginx:ro
ro rw 分别表示只读 读写
ro表示挂载的路径只能在宿主机内修改,不能在容器内修改

  • code ==失败中==

    ➜ ~ docker run -d -P --name nginx05 -v /Users/dada/Downloads/docker-centos/nginx/conf:/etc/nginx:ro nginx:latest
    
    ➜  ~ docker inspect 容器id
    
    

    使用数据卷 方式二

    初识Dockerfile
    Dockerfile就是用来构建docker镜像的构建文件,命令脚本,通过脚本可以生成镜像。

  • 可以完成数据卷挂载,
  • 镜像生成 docker build -f Dockerfile -t 镜像名称:TAG . #末尾必须有个点
  • 在Dockerfile文件的名字是Dockerfile的时候,docker build 可以不用指定-f
  • code
# 打印当前路径
➜  file pwd
/Users/dada/Downloads/docker-centos/file

# file路径下执行创建文件命令
➜  file touch Dockerfile1
# 编辑文件写入内容
➜  file vim Dockerfile1
# 查看是否写入成功
➜  file cat Dockerfile1 
FROM centos
VOLUME ["volume01","volume02"]
CMD echo "----end----"
CMD /bin/bash

# 命令行末尾缺少点 报错
➜  file docker build -f Dockerfile1 -t mycentos:02
"docker build" requires exactly 1 argument.
See \'docker build --help\'.

Usage:  docker build [OPTIONS] PATH | URL | -

Build an image from a Dockerfile

# 命令增加点 生成成功
➜  file docker build -f Dockerfile1 -t mycentos:02 .
[+] Building 0.1s (5/5) FINISHED                                                          
 => [internal] load build definition from Dockerfile1                                0.0s
 => => transferring dockerfile: 123B                                                 0.0s
 => [internal] load .dockerignore                                                    0.0s
 => => transferring context: 2B                                                      0.0s
 => [internal] load metadata for docker.io/library/centos:latest                     0.0s
 => CACHED [1/1] FROM docker.io/library/centos                                       0.0s
 => exporting to image                                                               0.0s
 => => exporting layers                                                              0.0s
 => => writing image sha256:231feafd3348cc7cb6a2eeed8b19effe7b15fd2a723a287669e6d06  0.0s
 => => naming to docker.io/library/mycentos:02                                       0.0s

Use \'docker scan\' to run Snyk tests against images to find vulnerabilities and learn how to fix them

# 查看新创建镜像
➜  file docker images|grep mycentos  
mycentos                             02                                                      231feafd3348   5 months ago    209MB
➜  file 

# 启动容器
➜  file docker run -d -it --name mycentos02 mycentos:02
0ff56e3d5516174f39c9eb63bbced886d8470d963ef6dcf77ce67082226860b9

#查看容器列表
➜  file docker ps|grep mycentos
0ff56e3d5516   mycentos:02            "/bin/sh -c /bin/bash"   37 seconds ago   Up 36 seconds             mycentos02

# inspect 查看容器数据卷挂载情况
➜  file docker inspect 0ff56e3d5516
"Mounts": [
            {
                "Type": "volume",
                "Name": "15a00b422c3ad4f7eac181566b51fc10d40e546b06a8d57100375aa58a0cc2b1",
                "Source": "/var/lib/docker/volumes/15a00b422c3ad4f7eac181566b51fc10d40e546b06a8d57100375aa58a0cc2b1/_data",
                "Destination": "volume02",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "volume",
                "Name": "9e520b5a5872379b57c8ade61125cedfd6f0e180712ade07d25d2d8808ce5a0a",
                "Source": "/var/lib/docker/volumes/9e520b5a5872379b57c8ade61125cedfd6f0e180712ade07d25d2d8808ce5a0a/_data",
                "Destination": "volume01",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
......
# 可以查看到volume01 volume02挂载成功
  • 测试不加 -f 生成镜像
    结论:在项目中Dockerfile文件的名字请使用“Dockerfile”,这是行业规范eg:composer.json go.mod等

    ➜  file ls
    Dockerfile1
    ➜  file mv Dockerfile1 Dockerfile  
    ➜  file docker build -t mycentos1:03 .
    [+] Building 0.1s (5/5) FINISHED                                                                                                                                                                                                              
     => [internal] load build definition from Dockerfile                                                                                                                                                                                     0.0s
     => => transferring dockerfile: 122B                                                                                                                                                                                                     0.0s
     => [internal] load .dockerignore                                                                                                                                                                                                        0.0s
     => => transferring context: 2B                                                                                                                                                                                                          0.0s
     => [internal] load metadata for docker.io/library/centos:latest                                                                                                                                                                         0.0s
     => CACHED [1/1] FROM docker.io/library/centos                                                                                                                                                                                           0.0s
     => exporting to image                                                                                                                                                                                                                   0.0s
     => => exporting layers                                                                                                                                                                                                                  0.0s
     => => writing image sha256:231feafd3348cc7cb6a2eeed8b19effe7b15fd2a723a287669e6d06e35aa6261                                                                                                                                             0.0s
     => => naming to docker.io/library/mycentos1:03                                                                                                                                                                                          0.0s
    
    Use \'docker scan\' to run Snyk tests against images to find vulnerabilities and learn how to fix them
    ➜  file docker images|grep mycentos1
    mycentos1                            03                                                      231feafd3348   5 months ago    209MB
    ➜  file 
    

    容器数据卷可以实现的功能1

    两个容器间数据同步,备份
    举例:两个MySQL同步数据库数据

  • --volumes-from 两个容器数据同步命令
  • code
# 启动3个容器
# docker01
➜  ~ docker run -d -it --name docker01 centos:latest
1a3e373b0d690d7f2c41577384e3a929d8c2067401d26eda2646e1547927952e
➜  ~ docker ps|grep docker0
1a3e373b0d69   centos:latest          "/bin/bash"              55 seconds ago   Up 54 seconds             docker01

# docker02 docker01的数据会同步到docker02
➜  ~ docker run -d -it --name docker02 --volumes-from docker01 centos:latest
297b7cbf22910888056b991abbb8e7ef141ed92b58ff60171025f7cb39cc27f1

#docker03 docker01的数据会同步到docker03
➜  ~ docker run -d -it --name docker03 --volumes-from docker01 centos:latest
9c5366c63559aac7a78aa9eec0bd7933de4de475652780d9e6e1cd94a113838c

#docker01 02 03会使用共同的数据卷
➜  ~ docker ps|grep docker0                                                 
9c5366c63559   centos:latest          "/bin/bash"              57 seconds ago       Up 56 seconds                 docker03
297b7cbf2291   centos:latest          "/bin/bash"              About a minute ago   Up About a minute             docker02
1a3e373b0d69   centos:latest          "/bin/bash"              5 minutes ago        Up 5 minutes                  docker01
# 删除docker01对数据有什么影响吗?
# 删除docker01对02 03没有影响,数据依旧在,备份机制
  • MySQL数据同步例子
  • code

    # mysql01
    ➜  ~ docker run -d -p 3301:3306 -v /etc/mysql/conf.d -v /var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql01 mysql:5.7
    2e20d35d29b85d7474d7e6c873db800022dcbf1f0a5f2a2402309691f354672a
    
    ➜  ~ docker ps|grep mysql01                                                                                                  
    2e20d35d29b8   mysql:5.7              "docker-entrypoint.s…"   13 seconds ago   Up 11 seconds   33060/tcp, 0.0.0.0:3301->3306/tcp, :::3301->3306/tcp   mysql01
    
    # mysql02 
    ➜  ~ docker run -d -p 3302:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql02 --volumes-from mysql01 mysql:5.7
    b6804fef3d73dd9648e35a18345d2dc654f6bf607f3aea1d274fe6d9edd720ba
    ➜  ~ docker ps|grep mysql02                                                                                  
    b6804fef3d73   mysql:5.7              "docker-entrypoint.s…"   7 seconds ago    Up 5 seconds    33060/tcp, 0.0.0.0:3302->3306/tcp, :::3302->3306/tcp   mysql02
    ➜  ~ 
    
  • 容器之间配置信息传递,数据卷容器生命周期一直持续到没有容器使用为止。但是一旦持久化到了宿主机,那么永远不会删除。

以上是关于docker容器数据卷的主要内容,如果未能解决你的问题,请参考以下文章

Docker学习笔记(8-2)Docker - 数据卷容器

docker数据卷容器

Docker 数据卷

docker数据卷容器

Docker之七:Docker数据卷管理

06-Docker-容器数据卷