>  기사  >  웹 프론트엔드  >  Docker 데이터 볼륨 고급 장

Docker 데이터 볼륨 고급 장

赶牛上岸
赶牛上岸원래의
2018-03-06 15:09:231410검색

Docker는 개발자가 애플리케이션과 종속성을 휴대용 컨테이너에 패키징한 다음 이를 가상화할 수도 있는 인기 있는 Linux 시스템에 게시할 수 있게 해주는 오픈 소스 애플리케이션 컨테이너 엔진입니다. 이 글은 주로 Docker 데이터 볼륨의 고급 버전을 소개하며 모든 분들께 도움이 되기를 바랍니다.

데이터 볼륨이 왜 필요한가요?

이것은 도커 컨테이너의 파일 시스템부터 시작해야 합니다. 효율성 등 여러 가지 이유로 호스트 머신에 도커 컨테이너의 파일 시스템이 복잡하게 존재하게 되는데, 이로 인해 다음과 같은 문제가 발생하게 됩니다.

  1. 컨테이너에 있는 파일은 호스트에서 쉽게 접근할 수 없습니다. 기계.

  2. 데이터는 여러 컨테이너 간에 공유될 수 없습니다.

  3. 컨테이너가 삭제되면 컨테이너에서 생성된 데이터도 손실됩니다.

이러한 문제를 해결하기 위해 Docker에서는 데이터 볼륨(Volume) 메커니즘을 도입했습니다. 데이터 볼륨은 하나 이상의 컨테이너에 존재하는 특정 파일 또는 폴더입니다. 이 파일 또는 폴더는 Docker 파일 시스템과 독립적으로 호스트 시스템에 존재합니다. 데이터 볼륨의 가장 큰 특징은 수명주기가 컨테이너의 수명주기와 무관하다는 것입니다.

데이터 볼륨 사용을 위한 최상의 시나리오

  1. 여러 컨테이너 간에 데이터를 공유합니다. 여러 컨테이너가 동시에 읽기 전용 또는 읽기-쓰기 모드로 동일한 데이터 볼륨을 마운트할 수 있으므로 데이터 볼륨의 데이터를 공유할 수 있습니다.

  2. 호스트가 고정 경로가 있는 특정 디렉터리나 파일이 존재해야 한다고 보장할 수 없는 경우 데이터 볼륨을 사용하면 이러한 제한으로 인해 발생하는 문제를 피할 수 있습니다.

  3. 원격 호스트나 클라우드 스토리지 등 호스트가 아닌 다른 곳에 컨테이너에 데이터를 저장하고 싶을 때.

  4. 다른 호스트 간에 컨테이너 데이터를 백업, 복원 또는 마이그레이션해야 하는 경우 데이터 볼륨을 선택하는 것이 좋습니다.

docker 볼륨 하위 명령

docker는 데이터 볼륨을 작동하기 위한 볼륨 하위 명령을 구체적으로 제공합니다.
create는 데이터 볼륨을 생성합니다.
inspect는 데이터 볼륨의 세부 정보를 표시합니다.
ls는 모든 데이터 볼륨을 나열합니다.
prune은 사용하지 않는 모든 데이터를 삭제합니다. 볼륨 사용된 볼륨 및 -f 옵션 있음
rm 사용하지 않은 볼륨을 하나 이상 삭제하고 -f 옵션 있음

먼저 hello라는 데이터 볼륨을 생성하고 ls 명령을 통해 확인합니다.

그런 다음 Inspection 명령을 사용하여 데이터 볼륨의 자세한 정보를 볼 수 있습니다.

여기서 데이터 볼륨이 생성된 시간을 볼 수 있습니다. 데이터 볼륨에서 사용하는 드라이버는 기본 "로컬"입니다. 데이터 볼륨은 호스트를 사용합니다. 호스트의 로컬 저장소는 기본적으로 로컬 시스템의 /var/lib/docker/volumes 아래에 있는 디렉터리인 데이터 볼륨의 마운트 지점입니다.

마지막으로 rm 또는 prune 명령을 사용하여 데이터 볼륨을 삭제할 수 있습니다. 나중에 저자는 실제 사용 시 데이터 볼륨 삭제와 관련된 몇 가지 사례를 소개합니다.

마운트 구문을 사용하여 데이터 볼륨 마운트

--volume(-v) 옵션을 사용하여 데이터 볼륨을 마운트하기 전에는 이제 docker가 데이터 볼륨을 관리하기 위해 더 강력한 --mount 옵션을 제공합니다. 마운트 옵션은 쉼표로 구분된 여러 키-값 쌍을 통해 여러 구성 항목을 한 번에 제공할 수 있으므로 마운트 옵션은 볼륨 옵션보다 더 자세한 구성을 제공할 수 있습니다. 마운트 옵션을 사용하여 일반적으로 사용되는

구성은 다음과 같습니다.

  1. type은 마운트 방법을 지정합니다. 실제로 여기서는 바인딩 및 tmpfs도 사용할 수 있습니다.

  2. volume-driver는 데이터 볼륨을 마운트할 드라이버를 지정합니다. 기본값은 로컬입니다.

  3. source는 명명된 데이터 볼륨의 경우 여기에 데이터 볼륨의 이름을 지정해야 합니다. 사용시 소스를 적어주셔도 되고, src로 줄여서 사용하셔도 됩니다.

  4. destination은 컨테이너에 탑재된 데이터의 경로를 지정합니다. 사용시 목적지를 적어주거나, dst, target 등으로 축약하여 사용할 수 있습니다.

  5. readonly는 마운트된 데이터가 읽기 전용임을 지정합니다.

  6. volume-opt를 여러 번 지정하여 더 많은 마운트 관련 구성을 개선할 수 있습니다.

아래의 구체적인 예를 살펴보겠습니다.

$ docker volume create hello
$ docker run -id --mount type=volume,source=hello,target=/world ubuntu /bin/bash

hello라는 데이터 볼륨을 생성한 다음 이를 컨테이너의 /world 디렉터리에 마운트했습니다. Inspection 명령을 통해 컨테이너 세부 정보의 "마운트" 정보를 보면 실제 데이터 볼륨 마운트 결과를 확인할 수 있습니다.

볼륨 드라이버를 사용하여 다른 위치에 데이터를 저장하세요

기본 데이터 외에 호스트에 저장된 데이터 볼륨에서 docker를 사용하면 볼륨 드라이버를 지정하여 Azrue Storge 또는 AWS S3와 같은 다른 위치의 데이터 볼륨에 데이터를 저장할 수도 있습니다.

简单起见,我们接下来的 demo 演示如何通过 vieux/sshfs 驱动把数据卷的存储在其它的主机上。

docker 默认是不安装 vieux/sshfs 插件的,我们可以通过下面的命令进行安装:

$ docker plugin install --grant-all-permissions vieux/sshfs

然后通过 vieux/sshfs 驱动创建数据卷,并指定远程主机的登录用户名、密码和数据存放目录:

docker volume create --driver vieux/sshfs \
 -o sshcmd=nick@10.32.2.134:/home/nick/sshvolume \
 -o password=yourpassword \
 mysshvolume

注意,请确保你指定的远程主机上的挂载点目录是存在的(demo 中是 /home/nick/sshvolume 目录),否则在启动容器时会报错。
最后在启动容器时指定挂载这个数据卷:

docker run -id \
 --name testcon \
 --mount type=volume,volume-driver=vieux/sshfs,source=mysshvolume,target=/world \
 ubuntu /bin/bash


这就搞定了,你在容器中 /world 目录下操作的文件都存储在远程主机的 /home/nick/sshvolume 目录中。进入容器 testcon 然后在 /world 目录中创建一个文件,然后打开远程主机的 /home/nick/sshvolume 目录进行查看,你新建的文件是不是已经出现在那里了!

数据卷原理

下图描述了 docker 容器挂载数据的三种方式:

数据卷是完全被 docker 管理的,就像上图中的黄色区域描述的一样,docker 在宿主机的文件系统中找了个文件管理数据卷相关的数据。因此你可能根本不需要知道数据卷文件在宿主机上的存储位置(事实上抱着刨根问底的精神我们还是很想搞清楚它背后的工作原理!)。

docker 数据卷的本质是容器中的一个特殊目录。在容器创建的过程中,docker 会将宿主机上的指定目录(一个以数据卷 ID 为名称的目录)挂载到容器中指定的目录上。这里使用的挂载方式为绑定挂载(bind mount),所以挂载完成后的宿主机目录和容器内的目标目录表现一致。

比如我们执行下面的命令创建数据卷 hello,并挂载到容器 testcon 的 /world 目录:

$ docker volume create hello
$ docker run -id --name testcon --mount type=volume,source=hello,target=/world ubuntu /bin/bash

实际上在容器的创建过程中,类似于在容器中执行了下面的代码:

// 将数据卷 hello 在宿主机上的目录绑定挂载到 rootfs 中指定的挂载点 /world 上
mount("/var/lib/docker/volumes/hello/_data", "rootfs/world", "none", MS_BIND, NULL)

在处理完所有的 mount 操作之后(真正需要 docker 容器挂载的除了数据卷目录还包括 rootfs,init-layer 里的内容,/proc 设备等),docker 只需要通过 chdir 和 pivot_root 切换进程的根目录到 rootfs 中,这样容器内部进程就只能看见以 rootfs 为根的文件系统以及被 mount 到 rootfs 之下的各项目录了。例如我们启动的 testcon 中的文件系统为:

下面我们介绍几个数据卷在使用中比较常见的问题。

数据的覆盖问题

  1. 如果挂载一个空的数据卷到容器中的一个非空目录中,那么这个目录下的文件会被复制到数据卷中。

  2. 如果挂载一个非空的数据卷到容器中的一个目录中,那么容器中的目录中会显示数据卷中的数据。如果原来容器中的目录中有数据,那么这些原始数据会被隐藏掉。

这两个规则都非常重要,灵活利用第一个规则可以帮助我们初始化数据卷中的内容。掌握第二个规则可以保证挂载数据卷后的数据总是你期望的结果。

在 Dockerfile 中添加数据卷

在 Dockerfile 中我们可以使用 VOLUME 指令向容器添加数据卷:

VOLUME /data

在使用 docker build 命令生成镜像并且以该镜像启动容器时会挂载一个数据卷到 /data 目录。根据我们已知的数据覆盖规则,如果镜像中存在 /data 目录,这个目录中的内容将全部被复制到宿主机中对应的目录中,并且根据容器中的文件设置合适的权限和所有者。

注意,VOLUME 指令不能挂载主机中指定的目录。这是为了保证 Dockerfile 的可一致性,因为不能保证所有的宿主机都有对应的目录。

在实际的使用中,这里还有一个陷阱需要大家注意:在 Dockerfile 中使用 VOLUME 指令之后的代码,如果尝试对这个数据卷进行修改,这些修改都不会生效!下面是一个这样的例子:

FROM ubuntu
RUN useradd nick
VOLUME /data
RUN touch /data/test.txt
RUN chown -R nick:nick /data

通过这个 Dockerfile 创建镜像并启动容器后,该容器中存在用户 nick,并且能够看到 /data 目录挂载的数据卷。但是 /data 目录内并没有文件 test.txt,更别说 test.txt 文件的所有者属性了。要解释这个现象需要我们了解通过 Dockerfile 创建镜像的过程:

Dockerfile 中除了 FROM 指令的每一行都是基于上一行生成的临时镜像运行一个容器,执行一条指令并执行类似 docker commit 的命令得到一个新的镜像。这条类似 docker commit 的命令不会对挂载的数据卷进行保存。

所以上面的 Dockerfile 最后两行执行时,都会在一个临时的容器上挂载 /data,并对这个临时的数据卷进行操作,但是这一行指令执行并提交后,这个临时的数据卷并没有被保存。因而我们最终通过镜像创建的容器所挂载的数据卷是没有被最后两条指令操作过的。我们姑且叫它 "Dockerfile 中数据卷的初始化问题"。

下面的写法可以解决 Dockerfile 中数据卷的初始化问题:

FROM ubuntu
RUN useradd nick
RUN mkdir /data && touch /data/test.txt
RUN chown -R nick:nick /data
VOLUME /data

通过这个 Dockerfile 创建镜像并启动容器后,数据卷的初始化是符合预期的。这是由于在挂载数据卷时,/data 已经存在,/data 中的文件以及它们的权限和所有者设置会被复制到数据卷中。

还有另外一种方法可以解决 Dockerfile 中数据卷的初始化问题。就是利用 CMD 指令和 ENTRYPOINT 指令的执行特点:与 RUN 指令在镜像构建过程中执行不同,CMD 指令和 ENTRYPOINT 指令是在容器启动时执行。因此使用下面的 Dockerfile 也可以达到对数据卷的初始化目的:

FROM ubuntu
RUN useradd nick
VOLUME /data
CMD touch /data/test.txt && chown -R nick:nick /data && /bin/bash

总结

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家支持php中文网。


相关推荐:

docker中安装phpredis实例分享

Docker搭建PHP开发环境方法

docker搭建laravel开发环境实例


위 내용은 Docker 데이터 볼륨 고급 장의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.