Docker 存储

目录

1、概念介绍

Storage Driver

无状态容器

有状态容器

Data Volume

2、bind mount

指定挂载文件只读权限

bind mount 挂载目录

3、docker manage volume

查看 volume

自定义 volume

使用 NFS 存储

4、共享数据

容器与host共享数据

volume container

data-packed volume container

5、Volume 的声明周期

备份 volume

6、Supervisor 进程管理工具


Docker容器存放数据的2种方法:第一种是由 storage driver 管理的镜像层和容器层;第二种是 Data Volume。

1、概念介绍
Storage Driver

Docker 支持多种 storage driver,有 AUFS、Device Mapper、Btrfs、OverlayFS、VFS 和 ZFS。它们都能实现分层的架构,同时又有各自的特性。

优先使用Linux 发行版默认的 storage driver。Docker 安装时会根据当前系统的配置选择默认的 driver。默认 driver 具有最好的稳定性,因为默认 driver 在发行版上经过了严格的测试。

# 查看 docker storage driver
docker info

无状态容器
有状态容器

对于某些容器,直接将数据放在由storage driver 维护的层中是很好的选择,比如那些无状态的应用。无状态意味着容器没有需要持久化的数据,随时可以从镜像直接创建。

有持久化数据的需求,容器启动时需要加载已有的数据,容器销毁时希望保留产生的新数据,这类容器是有状态的。有状态容器需要使用Data Volume存储数据

比如无状态容器 busybox,它是一个工具箱,我们启动 busybox 是为了执行wget,ping 之类的命令,不需要保存数据供以后使用,使用完直接退出,容器删除时存放在容器层中的工作数据也一起被删除。

Data Volume

Union File System

Docker 镜像是由多个文件系统(只读层)叠加而成。当我们启动一个容器的时候,Docker会加载只读镜像层并在其上(即镜像栈顶部)添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏。当删除Docker容器,并通过该镜像重新启动时,之前的更改将会丢失。在Docker中,只读层及在顶部的读写层的组合被称为Union File System(联合文件系统)。

Data Volume

为了能够保存(持久化)数据以及共享容器间的数据,Docker提出了Volume的概念, 简单来说,Volume就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。Data Volume 本质上是 Docker Host 文件系统中的目录或文件,直接被 mount 到容器的文件系统中。

Data Volume 特点:

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

docker 提供了两种类型的 volume:bind mount & docker managed volume

2、bind mount

bind mount 是将 host 上已存在的目录或文件 mount 到容器。类似于 Linux 下对目录进行 mount。

清空容器

# 清空容器
systemctl restart docker 
docker rm -v $(docker ps -aq -f status=exited)
  • 重启docker会关闭所有运行着的容器,除非添加--restart=always参数

挂载文件到容器

# 准备要挂载到容器的文件
mkdir /root/html
echo "hello apache" > html/index.html

# 把文件挂载到httpd容器网站根目录
docker run -p 80:80 \
-v /root/html/index.html:/usr/local/apache2/htdocs/index.html -d httpd
  • -v /host/path:/container/path,如果容器上的路径不存在,目录自动在给定的路径中创建

修改容器卷里的数据

 echo "nihao123" >> /root/html/index.html

删除容器,数据依然在宿主机目录中

# 删除容器
docker rm -f fff56a33bd5902

# 查看数据
cat /root/html/index.html 

指定挂载文件只读权限

bind mount 时还可以指定数据的读写权限,默认是可读可写,可指定为只读

docker run -it -p 80:80 \
-v /root/html/index.html:/usr/local/apache2/htdocs/index.html:ro httpd /bin/bash

bind mount 挂载目录
docker run -d -p 80:80 -v /root/html:/usr/local/apache2/htdocs:ro httpd 

3、docker manage volume

使用bind mount必须要知道宿主机的挂载目录,限制了容器的可移植性,当需要将容器迁移到其他host,而该 host 没有要 mount 的数据或者数据不在相同的路径时,操作会失败,移植性更好的方式是docker managed volume。

docker managed volume 与 bind mount 在使用上的最大区别是不需要指定 mount 源,指明容器挂载点就行了。

# 使用docker managed volume
docker run -d -p 81:80 -v /usr/local/apache2/htdocs httpd

# 查看宿主机挂载目录
docker inspect -f {{.Mounts}} c64d72a996394a

每当容器申请mount docker managed volume 时,docker 在/var/lib/docker/volumes下生成一个目录,这个目录就是 mount 源。

# 修改文件内容
echo "hello linux" >> /var/lib/docker/volumes/d3d2fc39c2c249694bb68e34dbe5f61f1b0cff9b203cbe6c843e976a26be0ab7/_data//index.html

查看 volume

查看 volume:docker volume ls

docker volume inspect  d3d2fc39c2c249694bb68e34dbe5f61f1b0cff9b203cbe6c843e976a26be0ab7

自定义 volume

语法:docker volume create --name volume_name

docker volume create --name data

# 使用自定义 volume
docker run -dit --name busybox1 -v data:/volume busybox

docker inspect -f {{.Mounts}} busybox1

使用 NFS 存储

服务端安装 nfs

yum install -y nfs-utils rpcbind
mkdir -p /data/nfs/docker
echo "/data/nfs *(rw,no_root_squash,sync)">>/etc/exports
systemctl start rpcbind nfs-server
systemctl enable rpcbind nfs-server
showmount -e localhost

客户端使用 nfs

yum install -y nfs-utils rpcbind
systemctl start rpcbind nfs-server
systemctl enable rpcbind nfs-server

docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.137.110,rw \
  --opt device=:/data/nfs \
  volume-nfs

③ 容器使用 volume-nfs

docker run -dit --name busybox2 -v volume-nfs:/nfs busybox

docker inspect -f {{.Mounts}} busybox2

4、共享数据

容器与host共享数据

我们有两种类型的data volume,它们均可实现在容器与 host 之间共享数据,但方式有所区别。

对于bind mount :直接将要共享的目录 mount 到容器。

对于docker managed volume 就要麻烦点。由于 volume 位于 host 中的目录,是在容器启动时才生成,所以需要将共享数据拷贝到 volume 中。

容器之间共享数据

将共享数据放在bind mount 中,然后将其mount到多个容器

# 启动3个httpd挂载相同的volume
docker run -d -p 82:80 -v /root/html:/usr/local/apache2/htdocs httpd
docker run -d -p 83:80 -v /root/html:/usr/local/apache2/htdocs httpd
docker run -d -p 84:80 -v /root/html:/usr/local/apache2/htdocs httpd

volume container

volume container 是专门为其他容器提供 volume 的容器。它提供的卷可以是 bind mount,也可以是 docker managed volume。

创建 volume container

docker create --name vc_data \
-v /root/html:/usr/local/apache2/htdocs \
-v /data/tools busybox

docker inspect -f {{.Mounts}} vc_data

容器挂载 vc_data

docker run -d --name web1 -p 85:80 --volumes-from vc_data httpd
docker run -d --name web2 -p 86:80 --volumes-from vc_data httpd
docker run -d --name web3 -p 87:80 --volumes-from vc_data httpd

# 查看web1目录挂载
docker inspect -f {{.Mounts}} web1

测试修改数据

data-packed volume container

volume container 的数据归根到底还是在host里, data-packed volume container可以将数据完全放到volume container 中,同时又能与其他容器共享。

使用 Dockerfile 构建镜像

cd /root/html/
vim Dockerfile
-----------------Dockerfile start ----------
FROM busybox
ADD index.html /usr/local/apache2/htdocs/
VOLUME /usr/local/apache2/htdocs/
-----------------Dockerfile end ------------

# 构建镜像
docker build -t datapacked .

创建 data-packed volume container

docker create --name vc_data1 datapacked

docker ps -a -f status=created

启动 httpd 容器

docker run -p 88:80 --name web4 --volumes-from vc_data1 -d httpd

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

5、Volume 的声明周期

Data Volume 中存放的是重要的应用数据, volume 生命周期管理包含 volume 的创建、共享和使用、备份、恢复、迁移和销毁 volume。

备份 volume

因为 volume 实际上是 host 文件系统中的目录和文件,所以 volume 的备份实际上是对文件系统的备份。

恢复 volume

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

迁移 volume

docker stop 当前容器

启动新版本容器并mount 原有volume,在启用新容器前要确保新版本的默认数据路径是否发生变化。

销毁 volume

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

docker不会销毁 bind mount,删除数据的工作只能由 host 负责。

对于 docker managed volume,在执行 docker rm 删除容器时可以带上-v参数,docker 会将容器使用到的 volume 一并删除,但前提是没有其他容器 mount 该 volume,目的是保护数据。

如果删除容器时没有带-v参数, 这样就会产生孤儿volume,可以使用docker volume rm进行删除

# 清空所有容器
systemctl restart docker
docker rm -v $(docker ps -aq -f status=exited)
docker rm -v $(docker ps -aq -f status=created)

# 查看孤儿volume
docker volume ls

# 批量删除孤儿 volume
docker volume rm $(docker volume ls -qf dangling=true)

6、Supervisor 进程管理工具

Docker 容器在启动的时候可以开启单个进程,比如,一个 ssh 或者 apache 的 daemon 服务。但我们经常也需要在一个容器上开启多个服务,这可以有很多方法,最简单的就是把多个启动命令放到一个启动脚本里面,启动的时候直接启动这个脚本。

编写 Dockerfile

mkdir httpd && cd httpd
vim Dockerfile
---------------------Dockerfile start ----------------------------------------
FROM centos:7
MAINTAINER from zhenglincong
#install supervisor
RUN yum install -y wget && wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo && yum install -y supervisor
#install ssh and apache
RUN yum install -q -y openssh-server httpd sudo
RUN useradd admin
RUN echo "admin:admin" | chpasswd
RUN echo "admin  ALL=(ALL)  ALL" >> /etc/sudoers
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN mkdir -p /var/run/sshd
RUN mkdir -p /home/admin/.ssh
RUN sed -ri 's/session reqired pam_loginuid.so/#session requied pam_loginuid.so/g' /etc/pam.d/sshd
RUN sed -i -r 's/^(.*pam_nologin.so)/#\1/' /etc/pam.d/sshd   #记得添加
RUN sed -ri 's/#ServerName www.example.com:80/ServerName www.exaple.com/g' /etc/httpd/conf/httpd.conf
ADD authorized_keys /home/admin/.ssh/authorized_keys
COPY supervisord.conf /etc/supervisord.conf
EXPOSE 22 80
CMD ["/usr/bin/supervisord"]
---------------------Dockerfile end ----------------------------------------

生成ssh秘钥对,并创建authorized_keys文件

ssh-keygen -t rsa
cat /root/.ssh/id_rsa.pub > /root/httpd/authorized_keys

supervisor配置文件内容

vim /root/httpd/supervisord.conf
----------------------------supervisord.conf-------------------
[supervisord]
nodaemon=true
[program:sshd]
command=/usr/sbin/sshd
[program:httpd]
command=/usr/sbin/httpd
----------------------------supervisord.conf-------------------
  • 第一段supervsord 配置软件本身,使用 nodaemon 参数来运行。nodaemon=true 如果是true,supervisord进程将在前台运行,默认为false,也就是后台以守护进程运行。
  • 下面2段包含我们要控制的 2 个服务。每一段包含一个服务的目录和启动这个服务的命令

构建镜像

docker build -t centos7.9_ssh_httpd_supervisord .

# 启动容器
docker run -d -p 1022:22 -p 80:80 centos7.9_ssh_httpd_supervisord
docker exec -it c6a21549f3b1  /bin/bash
ps -axf

①②③④⑤⑥⑦⑧⑨⑩

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值