简介

docker storage driver支持了image分层存储和容器可写层的存储管理,使用挂载主机目录的方式可以将数据存储在主机的文件系统上或内存中。

  1. 之前学习过镜像的分层存储,以Dockerfile构建镜像每行有关数据写入的命令会给镜像增加一层,容器基于镜像启动,会在镜像最上层之上再启动一层可写层(writable layer),如果容器被删除,那么该可写层也会消失,所以容器内的可写层不宜用来对需要持久化的数据做存储,应当存储一些临时数据,这些数据不影响应用的后续使用,比如之前使用的busybox用来执行wget、ping等命令,执行期间产生的数据我们无需保存,即使容器被删除,后面再次使用时启动新容器还是可以达到相同的目的。
  2. 可以使用volumes和bind mounts的方式将数据存储在主机上,这样即使容器被删除,数据仍然在,而且很容的对数据进行迁移与共享。
  3. 由于容器可写层需要storage dirver的支持,需要通过内核提供一个union filesystem,维护了额外的数据结构,相较于直接使用数据卷性能更差些,具体的实现方式在后面研究相关底层技术再记录,先整理下存储卷的相关知识。

挂载方式

有三种挂载方式将容器内部数据存储到主机上,Volumes、bind mounts、tmpfs mounts

Volumes

由docker创建和管理,主机上的其他程序不可修改,将数据卷存储在主机的一片区域上(linux路径/var/lib/docker/volumes/),使用某个volume其实是将该volume在主机上的目录mount到容器内,如果该目录下已有内容,则原有的数据会被复制到volume中。

使用场景

  1. 多个容器共享数据,多个容器可以同时挂载一个volume
  2. 允许使用volume driver,不需要更改应用程序,通过更换volume dirvier存储容器数据到远端主机或云端(例如NFS or S3)
  3. 备份和迁移数据
  1. # 创建volume
  2. docker volume create volume-test1
  3. # 查看volume详细信息
  4. docker volume inspect volume-test1
  5. # 删除volume,只有没有任何容器使用时才可删除(包括停止的容器)
  6. docker volume rm volume-test1

启动容器时指定volume参数

  1. # 启动容器nginx1,卷volume-test1挂载到nginx1内部的/app路径下
  2. docker run -d \
  3. --name nginx1 \
  4. --mount source=volume-test1,target=/app \
  5. nginx:latest
  • 如果将新建的volume挂载到容器某个目录下,并且该目录下已有内容,那么会将这些内容拷贝到volume中,其他容器使用该volume时也可以看到

使用volume driver

例如,使用vieux/sshfs驱动允许容器使用sshfs挂载远端文件夹

  1. # 下载vieux/sshfs驱动插件
  2. docker plugin install --grant-all-permissions vieux/sshfs
  3. # 使用vieux/sshfs驱动创建volume,驱动配置选项通过-o指定
  4. docker volume create --driver vieux/sshfs \
  5. -o sshcmd=test@node2:/home/test \
  6. -o password=testpassword \
  7. sshvolume1
  8. # 启动时创建并使用volume,volume-opt指定使用volume需要的参数
  9. docker run -d \
  10. --name sshfs-container \
  11. --volume-driver vieux/sshfs \
  12. --mount src=sshvolume2,target=/app,volume-opt=sshcmd=test@node2:/home/test,volume-opt=password=testpassword \
  13. nginx:latest

创建CIFS/Samba volume,可以直接使用容器挂载samba文件夹

  1. # local是默认的driver
  2. docker volume create \
  3. --driver local \
  4. --opt type=cifs \
  5. --opt device=//uxxxxx.your-server.de/backup \
  6. --opt o=addr=uxxxxx.your-server.de,username=uxxxxxxx,password=*****,file_mode=0777,dir_mode=0777 \
  7. --name cif-volume

备份volume

  1. # 创建一个容器dbstore
  2. docker run -v /app --name dbstore ubuntu /bin/bash
  3. # 再创建一个新容器,将主机当前目录$(pwd)挂载到新容器/backup目录下,新容器与容器dbstore共享其volume,之后运行新容器执行tar cvf /backup/backup.tar /app将/app目录归档到/backup/backup.tar下面(即主机$(pwd)下面)
  4. docker run --rm --volumes-from dbstore -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /app

恢复

  1. # 创建新的容器
  2. docker run -v /dbdata --name dbstore2 ubuntu /bin/bash
  3. # 共享新容器的volume卷,并将备份文件所在目录$(pwd)挂载到当前容器/backup下,解压backup.tar到容器dbstore2的/dbdata
  4. docker run --rm --volumes-from dbstore2 -v $(pwd):/backup ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar"

bind mounts

  1. 与volume不同的是,除了可以挂载目录,还可以挂载文件到容器内。

  2. 可以提供更好的性能,具体效果依赖主机使用的文件系统。

  3. 因为使用绝对路径与主机目录绑定,所以容器的移植性较volume更弱,隔离性差(其他程序也可以修改该路径的内容)。

  4. 可以对容器设置只读或读写权限

使用场景

  1. 将源代码目录挂载到容器中,在主机修改代码,可以看到容器应用的变化效果
  2. 共享主机文件到容器,比如将主机的/etc/resolv.conf挂载到容器,为容器提供DNS解析

使用bind mounts

  1. # 使用bind mounts,将主机target目录挂载到容器/app下,容器对该目录有只读权限
  2. docker run -d \
  3. -it \
  4. --name devtest \
  5. --mount type=bind,source="$(pwd)"/target,target=/app,readonly \
  6. nginx:latest
  • 如果容器目录已有内容,将主机目录bind mounts到该目录下时,容器该目录下原有的内容被隐藏,只显示主机目录下已有的内容

tmpfs mounts

tmpfs mounts方式与上两种不同,是将容器内该挂载点下的内容写到主机内存中,容器停止时候,挂载点被移除,这些内容就会丢失。

使用场景

  1. 存放一些临时的敏感信息(不想将其存放到主机或容器中)
  2. 容器应用需要写入大量的非持久化数据时提高性能

使用tmpfs mounts

  1. # 运行容器,使用tmpfs mounts到容器的/app目录下,设置容器内使用权限为770,/app目录大小为10M
  2. docker run -d -it \
  3. --name tmptest \
  4. --mount type=tmpfs,destination=/app,tmpfs-mode=1770 tmpfs-size=10m\
  5. nginx:latest
  • 默认tmpfs mounts不对目录大小做限制

小结

对于以上三种挂载方式,bind mounts与volumes的使用与功能差异较小,通过表格的方式对比下:

对比项(source:主机;dest:容器) bind mount volume
创建时主机路径不在 报错 自动创建
source路径 使用时指定 /var/lib/docker/volumes
source路径为空 隐藏dest,显示source内容 将dest内容复制到source后显示source内容
source路径不为空 隐藏dest,显示source内容 隐藏dest,显示source内容
可移植性 弱(绑定主机路径) 强(docker完全控制,不依赖主机路径)
主机程序访问 容易(chown修改用户组即可访问) 受限(需root用户)

学习自:

《Docker技术入门与实战(第3版)》Nigel,Poulton(奈吉尔·波尔顿) 著,李瑞丰,刘康 译

《深入浅出Docker》杨保华,戴王剑,曹亚仑 著

https://docs.docker.com/

https://shichen.blog.csdn.net/article/details/106292036

docker学习笔记(4)- 应用数据管理(容器外)的更多相关文章

  1. Docker学习笔记之镜像与容器

    0x00 概述 镜像和容器作为 Docker 里最基础的概念,我们很有必要了解 Docker 对它们的很多定义以及其他与它们有关的知识.在这一小节里,我们就专门针对镜像与容器两个概念展开,细致的梳理与 ...

  2. Docker学习笔记:镜像、容器、数据卷

    核心概念 镜像:一个只读的模板,类似虚拟机的镜像. 容器:可以理解为镜像的一个运行实例.运行时类似于沙箱,多个容器互相独立. 仓库:存放镜像文件的地方. 镜像 命令表格 命令 解释 选项 docker ...

  3. Docker学习笔记 - Docker容器内部署redis

    Docker学习笔记(2-4)Docker应用实验-redist server 和client的安装使用 一.获取redis容器(含客户端和服务端) 二.创建服务端容器 1.在终端A中运行redis- ...

  4. Docker学习笔记之-部署.Net Core 3.1项目到Docker容器,并使用Nginx反向代理(CentOS7)(一)

    上一节演示如何安装Docker,链接:Docker学习笔记之-在CentOS中安装Docker 本节演示 将.net core 3.1 部署到docker容器当中,并使用 Nginx反向代理,部署平台 ...

  5. Docker学习笔记之--.Net Core项目容器连接mssql容器(环境:centos7)

    前一节演示在docker中安装mssql,地址:Docker学习笔记之--安装mssql(Sql Server)并使用Navicat连接测试(环境:centos7) 本节演示 .Net Core项目容 ...

  6. Docker学习笔记之--.Net Core应用容器通过网桥连接Redis容器(环境:centos7)

    上节演示通过应用容器连接sql server容器,连接:Docker学习笔记之--.Net Core项目容器连接mssql容器(环境:centos7) 本节演示安装 redis容器,通过网桥连接 先决 ...

  7. Docker学习笔记之一,搭建一个JAVA Tomcat运行环境

    Docker学习笔记之一,搭建一个JAVA Tomcat运行环境 前言 Docker旨在提供一种应用程序的自动化部署解决方案,在 Linux 系统上迅速创建一个容器(轻量级虚拟机)并部署和运行应用程序 ...

  8. Docker学习笔记总结

    Docker学习笔记 https://yeasy.gitbooks.io/docker_practice/content/   一 环境搭建 Ubuntu安装 .添加软件源的GPG密钥 curl -f ...

  9. Docker:学习笔记(1)——基础概念

    Docker:学习笔记(1)——基础概念 Docker是什么 软件开发后,我们需要在测试电脑.客户电脑.服务器安装运行,用户计算机的环境各不相同,所以需要进行各自的环境配置,耗时耗力.为了解决这个问题 ...

  10. docker学习笔记1 -- 安装和配置

    技术资料 docker中文官网:http://www.docker.org.cn/ 中文入门课程:http://www.docker.org.cn/book/docker.html docker学习笔 ...

随机推荐

  1. PHP面试常考内容之面向对象(3)

    PHP面试专栏正式起更,每周一.三.五更新,提供最好最优质的PHP面试内容.继上一篇"PHP面试常考内容之面向对象(2)"发表后,今天更新面向对象的最后一篇(3).需要(1),(2 ...

  2. time模块以及datetime模块

    内容概要 time模块 **timestamp时间戳 **struct_time结构化时间 **format time格式化时间 datetime模块 **date **time **datetime ...

  3. Solution -「洛谷 P4719」「模板」"动态 DP" & 动态树分治

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个结点的带权树,\(m\) 次单点点权修改,求出每次修改后的带权最大独立集.   \(n,m\le10^5 ...

  4. Note -「单位根反演」学习笔记

    \(\mathcal{Preface}\)   单位根反演,顾名思义就是用单位根变换一类式子的形式.有关单位根的基本概念可见我的这篇博客. \(\mathcal{Formula}\)   单位根反演的 ...

  5. 在线pdf请你谨慎打开

    本篇其实算之前安全整改话题的一点补充,对之前内容感兴趣的可以走以下快捷通道: 安全漏洞整改系列(二) 安全漏洞整改系列(一) 背景 前不久某家客户对我们提供的系统又进行了一轮安全测试,其中有一条我觉得 ...

  6. tomcat 上传文件权限不足

    参考:https://www.cnblogs.com/houchaoying/p/8652040.html tomcat-bin-catalina.sh UMASK="0027" ...

  7. tor-browse

    https://sourceforge.net/projects/t-browser/

  8. 中国著名hacker---陈三堰

    在学习<网络攻防>这门课程中,我了解到了黑客之间的斗智斗勇,同样也对中国本土黑客产生了兴趣,之后,我将用一段时间扒一扒这其中比较有分量的传奇人物--陈三堰. 真名:陈三堰 网名:陈三少 所 ...

  9. 财务数据分析工具的选择:Excel还是大数据BI?

    ​财务数据分析一般都采用什么工具?跟财务数据分析的哪些指标有关?要怎样展现财务数据间的紧密关联? 财务报表分析比较复杂,一般来说主要包括以下项目: 1. 趋势:在多个时间段内为财务报表中的关键项目创建 ...

  10. 【C#基础概念】函数参数默认值和指定传参和方法参数

    函数参数默认值和指定传参 最近在编写代码时发现介绍C#参数默认值不能像PL/SQL那样直接设置default,网上也没有太多详细的资料,自己琢磨并试验后整理成果如下: C#允许在函数声明部分定义默认值 ...