docker中数据卷探究与总结

为实现持久化,docker引入了挂载数据卷的方法,以实现数据的可持久化。具体是以下三种:
一.通过docker run命令
命令:
docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/test.txt:/var/spool/cron/crontabs/root openfrontier/gerrit:2.15.3
此时将宿主机的/data/mysql1挂载到容器的/var/lib/mysql下,这里需要注意的还分以下几种情况:
A.挂载本地不存在的文件,到容器中已存在的文件,无法启动
docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/review_site_test/root:/var/spool/cron/crontabs/root openfrontier/gerrit:2.15.3

结果无法启动

B.挂载本地不存在的文件夹,到容器内已存在的文件夹,可以启动,但会清空容器内的指定目录/var/spool/cron/crontabs下的所有文件
docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/review_site_test:/var/spool/cron/crontabs openfrontier/gerrit:2.15.3

结果可以启动

但需要注意的是挂载本地不存在的文件夹过去,会清空当前容器的指定文件夹。如果容器中对该文件夹有启动依赖,例如上面的gerrit镜像:
使用下面的命令就无法启动:
docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/review-site21a:/usr/share/gitweb openfrontier/gerrit:2.15.3

原因:gerrit依赖于gitweb

C.挂载本地存在的文件,到容器内指定文件,可以启动,该文件会覆盖你指定的文件
[root@zzw docker]# cat test.txt
askdkjajksdk

[root@zzw docker]# docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/test.txt:/var/spool/cron/crontabs/root openfrontier/gerrit:2.15.3
c86aac5a73d551163c262bdf4db8cc4253322ac4c41d2d2418675c5b4f63e62a

bash-4.4# cd /var/spool/cron/crontabs
bash-4.4# ls
root
bash-4.4# vim root
bash: vim: command not found
bash-4.4# cat root
askdkjajksdk

D.挂载本地存在的文件夹test,到容器里已存在的文件夹,发现test目录中的文件,直接到容器内指定目录下
[root@zzw docker]# docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/test:/var/spool/cron/crontabs openfrontier/gerrit:2.15.3
9c32db2cff1d8d7ed3636a812302470d9408f4c60786067a57da770b930ae01f
[root@zzw docker]# docker exec -it gerrit /bin/bash
bash-4.4# cd /var/spool/cron/
bash-4.4# ls
crontabs
bash-4.4# cd crontabs
bash-4.4# ls
test.txt
bash-4.4# vim test.txt
bash: vim: command not found
bash-4.4# cat test.txt
askdkjajksdk

F.挂载本地存在的文件夹test,到容器里不存在的文件夹,会在容器内创建该test文件夹
E的变种
[root@zzw docker]# docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/test:/var/spool/cron/test openfrontier/gerrit:2.15.3
53fb24583eb65278599975ca515000080267e8348e945f1fcbd4fc4f8e6cb165
[root@zzw docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
53fb24583eb6 openfrontier/gerrit:2.15.3 "/gerrit-entrypoin..." 4 seconds ago Up 2 seconds 0.0.0.0:9001->8080/tcp, 0.0.0.0:29419->29418/tcp gerrit
d114a167bbcc nginx:1.15.2-alpine "nginx -g ‘daemon ..." 41 hours ago Exited (0) 35 minutes ago test_nginx_1
641508207b44 mysql:5.7 "docker-entrypoint..." 41 hours ago Exited (0) 35 minutes ago test_db_1
[root@zzw docker]# docker exec -it gerrit /bin/bash
bash-4.4# cd /var/spool/cron/
bash-4.4# ls
crontabs test
bash-4.4# cd test/
bash-4.4# ls
test.txt

G.挂载本地是文件test.txt,到容器内指定的目录crontabs,报错
[root@zzw docker]# docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/test/test.txt:/var/spool/cron/crontabs openfrontier/gerrit:2.15.3
e63487c08abce10c8bdbcf834714ad0994a93118abdd5126969856f862ca7f0b
/usr/bin/docker-current: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "process_linux.go:364: container init caused \"rootfs_linux.go:54: mounting \\"/home/docker/test/test.txt\\" to rootfs \\"/var/lib/docker/overlay2/5b0428b09a0727e114f06d312106e4fb28bc31d728abd27dab2f30328497c3c7/merged\\" at \\"/var/lib/docker/overlay2/5b0428b09a0727e114f06d312106e4fb28bc31d728abd27dab2f30328497c3c7/merged/etc/crontabs\\" caused \\"not a directory\\"\""
: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type.

看过第一种肯定有一些疑惑,因为有些镜像是违背第一种原则,即宿主机不存在某个目录,-v参数指定的宿主机目录:容器目录,容器目录里的东西立马都到宿主机指定的目录下了,不是因为宿主机的空目录覆盖掉容器的指定目录吗?怎么容器目录里的东西全都过来呢?
例如你用这条命令试试:
docker run -dit --name gerrit -p 9001:8080 -p 29419:29418 -v /home/docker/test1:/var/gerrit/review_site openfrontier/gerrit:2.15.3

别着急等会儿解释。

二.通过dockerfile中的volume创建挂载点
下面我们看下mysql的dockerfile

FROM debian:stretch-slim

# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mysql && useradd -r -g mysql mysql

RUN apt-get update && apt-get install -y --no-install-recommends gnupg dirmngr && rm -rf /var/lib/apt/lists/*

# add gosu for easy step-down from root
ENV GOSU_VERSION 1.7
RUN set -x     && apt-get update && apt-get install -y --no-install-recommends ca-certificates wget && rm -rf /var/lib/apt/lists/*     && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture)"     && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$(dpkg --print-architecture).asc"     && export GNUPGHOME="$(mktemp -d)"     && gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4     && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu     && gpgconf --kill all     && rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc     && chmod +x /usr/local/bin/gosu     && gosu nobody true     && apt-get purge -y --auto-remove ca-certificates wget

RUN mkdir /docker-entrypoint-initdb.d

RUN apt-get update && apt-get install -y --no-install-recommends # for MYSQL_RANDOM_ROOT_PASSWORD
        pwgen # for mysql_ssl_rsa_setup
        openssl # FATAL ERROR: please install the following Perl modules before executing /usr/local/mysql/scripts/mysql_install_db:
# File::Basename
# File::Copy
# Sys::Hostname
# Data::Dumper
        perl     && rm -rf /var/lib/apt/lists/*

RUN set -ex; # gpg: key 5072E1F5: public key "MySQL Release Engineering <mysql-build@oss.oracle.com>" imported
    key=‘A4A9406876FCBD3C456770C88C718D3B5072E1F5‘;     export GNUPGHOME="$(mktemp -d)";     gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$key";     gpg --batch --export "$key" > /etc/apt/trusted.gpg.d/mysql.gpg;     gpgconf --kill all;     rm -rf "$GNUPGHOME";     apt-key list > /dev/null

ENV MYSQL_MAJOR 5.7
ENV MYSQL_VERSION 5.7.25-1debian9

RUN echo "deb http://repo.mysql.com/apt/debian/ stretch mysql-${MYSQL_MAJOR}" > /etc/apt/sources.list.d/mysql.list

# the "/var/lib/mysql" stuff here is because the mysql-server postinst doesn‘t have an explicit way to disable the mysql_install_db codepath besides having a database already "configured" (ie, stuff in /var/lib/mysql/mysql)
# also, we set debconf keys to make APT a little quieter
RUN {         echo mysql-community-server mysql-community-server/data-dir select ‘‘;         echo mysql-community-server mysql-community-server/root-pass password ‘‘;         echo mysql-community-server mysql-community-server/re-root-pass password ‘‘;         echo mysql-community-server mysql-community-server/remove-test-db select false;     } | debconf-set-selections     && apt-get update && apt-get install -y mysql-server="${MYSQL_VERSION}" && rm -rf /var/lib/apt/lists/*     && rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld     && chown -R mysql:mysql /var/lib/mysql /var/run/mysqld # ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
    && chmod 777 /var/run/mysqld # comment out a few problematic configuration values
    && find /etc/mysql/ -name ‘*.cnf‘ -print0         | xargs -0 grep -lZE ‘^(bind-address|log)‘         | xargs -rt -0 sed -Ei ‘s/^(bind-address|log)/#&/‘ # don‘t reverse lookup hostnames, they are usually another container
    && echo ‘[mysqld]\nskip-host-cache\nskip-name-resolve‘ > /etc/mysql/conf.d/docker.cnf

VOLUME /var/lib/mysql

COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s usr/local/bin/docker-entrypoint.sh /entrypoint.sh # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"]

EXPOSE 3306 33060
CMD ["mysqld"]

很明显有个标签:
VOLUME
这个标签我理解是将容器目录暴露出去,简单理解就是容器中的目录可以挂载到宿主机的某个匿名目录,一般是在docker的主程序目录下,一般没做修改的话就是/var/lib/docker下,我这里是/data/docker
来看下具体命令:

那么我们到标红的那段里面看看,是否和/var/lib/mysql一样呢?结果是一样的

那老是匿名不是个事,我们能指定吗?
第一种方法-v不就行了吗?
下面试试:

结果发现是可以了,/var/lib/mysql里的东西全部到/data/mysql1里面了,这里其实是容器的目录复制到指定目录,宿主机的指定目录再挂载到容器的指定目录中,这理解起来可能有些困难,但是确实是这样。
那么我们就很好解决了上面gerrit数据卷的问题了,因为它的dockerfile里面也是有VOLUME标签的。

三.使用--volumes-from参数指定挂载的容器的宿主机目录
上图,不多bb

可以发现mysql1和mysql用的是用一个宿主机目录/data/mysql1

好了,数据卷东西就写到这了

原文地址:http://blog.51cto.com/9237101/2350563

时间: 2024-10-12 19:41:58

docker中数据卷探究与总结的相关文章

(九) Docker 容器数据卷(挂载)

一.容器数据卷 docker 容器数据卷是容器在运行过程中持久化数据的一种方式,卷是目录或文件,存在于一个或多个容器中,由docker 挂载到容器,但不属于联合文件系统,因此能够绕过Union File System  提供一些用于持续存储或共享数据的特性:卷的设计目的就是数据持久化,完全独立于容器的生命周期,因此docker不会在容器删除时,删除其挂载的数据卷. 特点: 数据卷可在容器之间共享或重用数据. 卷中的更改可以直接生效. 数据卷中的更改,不会包含在镜像中的更新. 数据卷的生命周期一直

5、docker容器数据卷

Docker容器数据卷 是什么 一句话:有点类似我们Redis里面的rdb和aof文件 能干嘛 容器的持久化 容器间继承+共享数据 数据卷 容器内添加 直接命令添加 命令 docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名 查看数据卷是否挂载成功 容器和宿主机之间数据共享 容器停止退出后,主机修改后数据是否同步 命令(带权限) docker run -it -v /宿主机绝对路径目录:/容器内目录:ro 镜像名 DockerFile添加 根目录下新建mydocker文

docker之数据卷

docker的数据管理:    数据卷:        一个绕过UFS的特殊目录,可供多个容器使用.        特性:            1.可以在容器之间共享和重用            2.数据卷的修改会立即生效            3.更新数据卷不影响image            4.数据卷会一直存在,直到没有容器使用 方式1:创建数据卷            创建容器的时候使用-v CONTDIR 指定数据卷. 方式2:挂载宿主机的目录作为数据卷            创建

docker创建数据卷以及数据卷容器

docker容器管理有2中方式: 1:数据卷:类似Linux下目录挂载mount 2:数据卷容器:其实就是一个正常的容器,专门用来提供数据卷供其它容器挂载的 使用docker search xxx //xxx指的是搜索相应的镜像.搜索后根据自己需求进行pull 下载镜像 [email protected] :~# docker pull jdeathe/centos-ssh 查看pull后的镜像 [email protected] :~# docker images REPOSITORY    

Docker之数据卷和数据卷容器

数据卷是一个可供容器使用的特殊目录,可以在容器之间共享和重用,对数据卷的修改会马上生效,卷会一直存在直到没有容器使用,数据卷的使用类似于mount 数据卷容器就是一个普通的容器,可专门提供数据卷供其他容器挂载使用,可以在容器之间共享一些持续更新的数据 1:创建数据卷 利用镜像centos,创建一个名为tomcat的容器,并在后台以守护进程方式工作,且将本地的/b2b/目录挂在在新建立的tomcat容器的/test目录下 [email protected]:/home/zxl# docker ru

自己学Docker:7.数据卷容器的备份、恢复

最近由于工作的原因,各种事情,忙的要死.用户发现软件有问题,也不管是不是自己操作的问题,一口就咬定是软件的问题,询问什么问题时就"有问题"三个字回应也是醉了. 烦心事过去就不说,之前一直关于Docker看到了数据卷容器,就像知道数据卷容器有什么用处.查了不少资料,最基本的用处还是利用数据卷容器来备份.恢复.迁移数据卷. 备份 我们先创建一个data容器. sudo docker run -i -t -v /data --name data c9fc7f8eec37 根据之前Docker

Docker之数据卷Volume(七)

一.简介 Docker数据卷(volume)机制.volume是存在于一个或多个容器中的特定文件或文件夹,这个目录以独立于联合文件系统的形式在宿主机中存在,并为数据的共享与持久化提供便利. 1)volume在容器创建时就会初始化,在容器运行时就可以使用其中的文件 2)volume能在不同的容器之间共享和重用 3)对volume中数据的操作会马上生效 4)对volume中数据的操作不会影响到镜像本身 5)volume的生存周期独立于容器的生存周期,即使删除容器,volume仍然会存在,没有任何容器

docker 12 docker容器数据卷

数据卷概念 ♣我们知道,当我们把一个运行中的容器关闭后,容器里的数据就没有了(如果你做了docker commit操作,数据会保留到新的镜像里面).所以我们就需要用容器数据卷把容器数据进行持久化储存. ♣还有一种情况,就是希望容器之间能共享数据,这时也需要容器数据卷. ♣一句话,数据卷就是用来解决数据持久化和数据共享的. ♣卷就是目录或者文件,存在一个或者多个容器中,由docker宿主机挂载到容器上,但是不属于联合文件系统,因此能绕过联合文件系统提供一些用于持久化存储或者共享数据的特性. ♣卷的

Docker系列-第五篇Docker容器数据卷

1.是什么 在生产环境中使用 Docker,往往需要对数据进行持久化,或者需要在多个容器之间进行数据共享,这必然涉及容器的数据管理操作 . 容器中的管理数据主要有两种方式 : 数据卷 ( Data Volumes ) : 容器内数据直接映射到本地主机环境: 数据卷容器( Data Volume Containers ) : 使用特定容器维护数据卷. 一句话:有点类似我们Redis里面的rdb和aof文件 将运用与运行的环境打包形成容器运行 ,运行可以伴随着容器,但是我们对数据的要求希望是持久化的