docker存储

docker存储

文章目录

Docker 两种存放数据资源

  1. 由 storage driver 管理的镜像层和容器层。
    • 容器由最上面一个可写的容器层,以及若干只读的镜像层组成,容器的数据就存放在这些层中。这样的分层结构最大的特性是 Copy-on-Write。对于某些容器,直接将数据放在由 storage driver 维护的层中是很好的选择,比如那些无状态的应用。无状态意味着容器没有需要持久化的数据,随时可以从镜像直接创建。
  2. Data Volume。
    • 是目录或文件,而非没有格式化的磁盘。数据可以被永久的保存,即使使用它的容器已经销毁。
bash 复制代码
#查看CentOS的默认 driver
[root@docker ~]# docker info

#CentOS Stream 8 用的overlay2,底层文件系统是xfs,各层数据存放在 /var/lib/docker。

Data Volume

  1. Data Volume 是目录或文件,而非没有格式化的磁盘(块设备)。
  2. 容器可以读写 volume 中的数据。
  3. volume 数据可以被永久的保存,即使使用它的容器已经销毁。

bind mount

bind mount 是将 host 上已存在的目录或文件 mount 到容器。

bash 复制代码
#例如 docker host 上有目录 $HOME/htdocs:
[root@docker ~]# pwd
/root
[root@docker ~]# mkdir htdocs
[root@docker ~]# cd htdocs/
[root@docker htdocs]# touch index.html
[root@docker htdocs]# vim index.html
<html><body><h1>This is a file in host file system !</h1></body></html>
[root@docker htdocs]# cd ..
[root@docker ~]# cat htdocs/index.html
<html><body><h1>This is a file in host file system !</h1></body></html>

#通过 -v 将其 mount 到 httpd 容器:
[root@docker ~]# docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs httpd

[root@docker ~]# curl 127.0.0.1:80
<html><body><h1>This is a file in host file system !</h1></body></html>

[root@docker ~]# echo "updated index page!" > ~/htdocs/index.html
[root@docker ~]# curl 127.0.0.1:80
updated index page!

#容器销毁
[root@docker ~]# docker stop 883f8a22b2be
883f8a22b2be
[root@docker ~]# docker rm 883f8a22b2be
883f8a22b2be
[root@docker ~]# cat ~/htdocs/index.html
updated index page!

#指定数据的读写权限,默认是可读可写,可指定为只读
[root@docker ~]# docker run -d -p 80:80 -v ~/htdocs:/usr/local/apache2/htdocs:ro 
httpd
bf1f526ddde7a7babb29adc091eef039628ba2eb288e6db33c9ccd946cc5d5f1
[root@docker ~]# docker exec -it bf1f526ddde7 bash
root@bf1f526ddde7:/usr/local/apache2# echo "do some changes" > htdocs/index.html
bash: htdocs/index.html: Read-only file system

#单独指定一个文件

#删除上一个容器不然80端口冲突
[root@docker ~]# docker rm - f bf1f526ddde7
#运行新容器用单独文件绑定
[root@docker ~]# docker run -d -p 80:80 -v 
~/htdocs/index.html:/usr/local/apache2/htdocs/new_index.html httpd
643e8820e98a17b977a984903ddfa6f37dcae3d705d45b624d0fce5c94fecb0c
[root@docker ~]# curl 127.0.0.1:80
<html><body><h1>It works!</h1></body></html>
[root@docker ~]# curl 127.0.0.1:80/new_index.html
updated index page!

#使用 bind mount 单个文件的场景是:只需要向容器添加文件,不希望覆盖整个目录。

docker managed volume

docker managed volume 与 bind mount 在使用上的最大区别是不需要指定 mount 源,指明 mount point 就行。

创建过程
  1. 容器启动时,简单的告诉 docker "我需要一个 volume 存放数据,帮我 mount 到目录 /abc"。
  2. docker 在 /var/lib/docker/volumes 中生成一个随机目录作为 mount 源。
  3. 如果 /abc 已经存在,则将数据复制到 mount 源。
  4. 将 volume mount 到 /abc
bash 复制代码
[root@docker ~]# docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd

#查找data volume具体位置
[root@docker ~]# docker inspect c75f36c4bf32 #docker inspect后面跟的是容器ID

[root@docker ~]# ls -l 
/var/lib/docker/volumes/1cc915096121dea197bbbb93fc90e6491d530e0c9e2ace1de07e2a635
e569d16/_data
total 4
-rw-r--r-- 1 501 ftp 26 Sep 17 21:08 index.html
[root@docker ~]#
[root@docker ~]# curl 127.0.0.1:80
<html><body><h1>It works!</h1></body></html>

#如果 mount point 指向的是已有目录,原有数据会被复制到 volume 中。

#它已经是一个 data volume。我们可以像 bind mount 一样对数据进行操作,更新数据。

#除了通过 docker inspect 查看 volume,我们也可以用 docker volume 命令

[root@docker ~]# docker volume ls
DRIVER   VOLUME NAME
local     1cc915096121dea197bbbb93fc90e6491d530e0c9e2ace1de07e2a635e569d16
[root@docker ~]#
[root@docker ~]# docker volume inspect 1cc915096121dea197bbbb93fc90e6491d530e0c9e2ace1de07e2a635e569d16

共享数据

容器与 host 共享数据

docker cp 可以在容器和 host 之间拷贝数据,当然我们也可以直接通过 Linux 的 cp 命令复制到 /var/lib/docker/volumes/xxx。

bash 复制代码
#docker managed volume 

[root@docker ~]# docker run -d -p 80:80 -v /usr/local/apache2/htdocs httpd
889b9d5309bd12499f8e4ee78a491d9ba7acef5660be00f30cda6569c9974c6f
[root@docker ~]#
[root@docker ~]# curl 127.0.0.1:80
<html><body><h1>It works!</h1></body></html>
[root@docker ~]#
[root@docker ~]# docker cp ~/htdocs/index.html 889b9d5309bd:/usr/local/apache2/htdocs  #将host os的/root/htdocs/index.html拷贝到容器中的/usr/local/apache2/htdocs目录下
Successfully copied 2.05kB to 889b9d5309bd:/usr/local/apache2/htdocs
[root@docker ~]#
[root@docker ~]# curl 127.0.0.1:80
updated index page!
[root@docker ~]#
容器之间共享数据
bash 复制代码
[root@docker ~]# docker run --name web1 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
994e75ef90a80365d7ea7733c727c3b1d24e5423d59a74185304462b7137d774
[root@docker ~]#
[root@docker ~]# docker run --name web2 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
28ff7c72d18b30123ff7e383db211890a0007e48817cdc73e7f50e9f2233eee6
[root@docker ~]#
[root@docker ~]# docker run --name web3 -d -p 80 -v ~/htdocs:/usr/local/apache2/htdocs httpd
160d823d985bad0ce7c27a0d301956f3c7ab4e9ca34c5be2601b3374fa30f6f1
[root@docker ~]#

[root@docker ~]# docker ps
CONTAINER ID   IMAGE     COMMAND              CREATED          STATUS          PORTS                                     NAMES
160d823d985b   httpd     "httpd-foreground"   13 seconds ago   Up 12 seconds   0.0.0.0:32770->80/tcp, :::32770->80/tcp   web3
28ff7c72d18b   httpd     "httpd-foreground"   19 seconds ago   Up 18 seconds   0.0.0.0:32769->80/tcp, :::32769->80/tcp   web2
994e75ef90a8   httpd     "httpd-foreground"   29 seconds ago   Up 27 seconds   0.0.0.0:32768->80/tcp, :::32768->80/tcp   web1
[root@docker ~]#
[root@docker ~]# curl 127.0.0.1:32770                #这个32770端口是host os映射到web3的duan'k
updated index page!
[root@docker ~]# curl 127.0.0.1:32769
updated index page!
[root@docker ~]# curl 127.0.0.1:32768
updated index page!
[root@docker ~]#

[root@docker ~]# echo "This is a new index page for web cluster" > ~/htdocs/index.html
[root@docker ~]#
[root@docker ~]# curl 127.0.0.1:32770
This is a new index page for web cluster
[root@docker ~]# curl 127.0.0.1:32769
This is a new index page for web cluster
[root@docker ~]# curl 127.0.0.1:32768
This is a new index page for web cluster
[root@docker ~]#
用volume container共享数据

容器只需与 volume container 关联,实现了容器与 host 的解耦

容器 mount 了两个 volume:

  1. bind mount,存放 web server 的静态文件。
  2. docker managed volume,存放一些实用工具(当然现在是空的,这里只是做个示例)。
bash 复制代码
[root@docker ~]# docker create --name vc_data \
 -v ~/htdocs/:/usr/local/apache2/htdocs \
 -v /other/userful/tools \
 busybox
bb4a33bf34aa7817ea752db83079aff15a5dfd77c23363f2e8dd3096d1cb910f

[root@docker ~]# docker inspect vc_data
...
        "Mounts": [
            {
                "Type": "volume",
                "Name": "4500300655eb8e32a5d88174395a61ea394e17266fbde60f224d815a7a9557e0",
                "Source": "/var/lib/docker/volumes/4500300655eb8e32a5d88174395a61ea394e17266fbde60f224d815a7a9557e0/_data",
                "Destination": "/other/userful/tools",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            },
            {
                "Type": "bind",
                "Source": "/root/htdocs",
                "Destination": "/usr/local/apache2/htdocs",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
...

#其他容器可以通过 `--volumes-from` 使用 `vc_data` 这个 volume container

[root@docker ~]# docker run --name web1 -d -p 80 --volumes-from vc_data httpd
362f039b562e4bf0020c38839a69bfd62733f27fda5481eb5b58178f41318ffe
[root@docker ~]#
[root@docker ~]# docker run --name web2 -d -p 80 --volumes-from vc_data httpd
217c1a243bb9a1f32ccae9ae2792e3720263d36402bbac58f43cfb068bc21e66
[root@docker ~]#
[root@docker ~]# docker run --name web3 -d -p 80 --volumes-from vc_data httpd
ce00b5fa458fc1af01e82ce8b43e8c072c858a669c1298add8053cbc7ac9f49b
[root@docker ~]#
data-packed volume container

data-packed volume container 是自包含的,不依赖 host 提供数据,具有很强的移植性,非常适合 只使用 静态数据的场景,比如应用的配置信息、web server 的静态文件等。

bash 复制代码
[root@docker ~]# vim Dockerfile
FROM busybox:latest
ADD htdocs /usr/local/apache2/htdocs
VOLUME /usr/local/apache2/htdocs

[root@docker ~]# echo "This content is from a data packed volume container!" > htdocs/index.html

[root@docker ~]# docker build -t datapacked .

[root@docker ~]# docker create --name vc_data datapacked
55dc035deeb31907830ea45f7af5e209c7e48078d59732798c529e7445d2a196

[root@docker ~]# docker run -d -p 80:80 --volumes-from vc_data httpd
98db78fc661441ec7ce0a2b76d62675fccf3389b7768cc9744b852645323c33b
[root@docker ~]#
[root@docker ~]# curl 127.0.0.1:80
This content is from a data packed volume container!

volume生命周期管理

备份

bash 复制代码
[root@docker ~]# docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:2
Unable to find image 'registry:2' locally
2: Pulling from library/registry
1cc3d825d8b2: Pull complete
85ab09421e5a: Pull complete
40960af72c1c: Pull complete
e7bb1dbb377e: Pull complete
a538cc9b1ae3: Pull complete
Digest: sha256:ac0192b549007e22998eb74e8d8488dcfe70f1489520c3b144a6047ac5efbe90
Status: Downloaded newer image for registry:2
a8214201171f28a13803c647ef84acdc982465c230cb5c6a034bd05574948408
[root@docker ~]#

#所有的本地镜像都存在 host 的 /myregistry 目录中,我们要做的就是定期备份这个目录

#volume 的恢复也很简单,如果数据损坏了,直接用之前备份的数据拷贝到 /myregistry 就可以了。

迁移

如果我们想使用更新版本的 Registry,这就涉及到数据迁移,方法是:

  1. docker stop 当前 Registry 容器。

  2. 启动新版本容器并 mount 原有 volume。

    docker run -d -p 5000:5000 -v /myregistry:/var/lib/registry registry:latest

当然,在启用新容器前要确保新版本的默认数据路径是否发生变化。

销毁

可以删除不再需要的 volume,但一定要确保知道自己正在做什么,volume 删除后数据是找不回来的。

docker 不会销毁 bind mount,删除数据的工作只能由 host 负责。对于 docker managed volume,在执行 docker rm 删除容器时可以带上 -v 参数,docker 会将容器使用到的 volume 一并删除,但前提是没有其他容器 mount 该 volume,目的是保护数据。

如果删除容器时没有带 -v ,这样就会产生孤儿 volume,好在 docker 提供了 volume 子命令可以对 docker managed volume 进行维护。

bash 复制代码
[root@docker ~]# docker volume ls
DRIVER    VOLUME NAME
[root@docker ~]#
[root@docker ~]# docker run --name bbox -v /test/data busybox
[root@docker ~]#
[root@docker ~]# docker volume ls
DRIVER    VOLUME NAME
local     8645b8e2edb91820799e6e8807d8b3476f1c5cec40beb14240b0e5143050e5e1

[root@docker ~]# docker rm bbox
bbox
[root@docker ~]# docker volume ls
DRIVER    VOLUME NAME
local     8645b8e2edb91820799e6e8807d8b3476f1c5cec40beb14240b0e5143050e5e1
[root@docker ~]#

[root@docker ~]# docker volume rm 8645b8e2edb91820799e6e8807d8b3476f1c5cec40beb14240b0e5143050e5e1
8645b8e2edb91820799e6e8807d8b3476f1c5cec40beb14240b0e5143050e5e1
[root@docker ~]#
[root@docker ~]# docker volume ls
DRIVER    VOLUME NAME
[root@docker ~]#

#批量删除
docker volume rm $(docker volume ls -q)

4240b0e5143050e5e1

root@docker \~\]# \[root@docker \~\]# docker volume rm 8645b8e2edb91820799e6e8807d8b3476f1c5cec40beb14240b0e5143050e5e1 8645b8e2edb91820799e6e8807d8b3476f1c5cec40beb14240b0e5143050e5e1 \[root@docker \~\]# \[root@docker \~\]# docker volume ls DRIVER VOLUME NAME \[root@docker \~\]# #批量删除 docker volume rm $(docker volume ls -q) ``` ```

相关推荐
小义_2 小时前
随笔 1(Linux)
linux·运维·服务器·网络·云原生·红帽
无名-CODING2 小时前
从零开始!Vue3+SpringBoot前后端分离项目Docker部署实战(上):环境搭建与数据库容器化
数据库·spring boot·docker
向往着的青绿色2 小时前
雷池(SafeLine)社区版免费部署教程|从环境检查到防护实操全流程
网络·计算机网络·nginx·网络安全·容器·网络攻击模型·信息与通信
HalvmånEver2 小时前
Linux:socket套接字编程的基础概念
linux·运维·服务器
Sst的头号粉丝3 小时前
Kubernetes——介绍
云原生·容器·kubernetes
木二_3 小时前
057.Kubernetes cert-manager ACME方案介绍
云原生·容器·kubernetes·证书·cert-manager·证书管理
二进制person3 小时前
JavaEE初阶 --网络初识
运维·服务器·网络
IMPYLH3 小时前
Linux 的 cp 命令
linux·运维·服务器
贝锐3 小时前
立航货运携手贝锐向日葵,大型物流园区如何进行远程运维升级
运维·远程