如何部署 docker 容器和关联的数据容器,包括内容?

Kry*_*ten 19 docker

我首先要承认我对 Docker 还很陌生,而且我可能是从错误的假设集来解决这个问题的……如果是这种情况,请告诉我。我已经看到很多关于 Docker 如何用于部署的讨论,但没有关于它实际如何完成的示例。

这是我认为它会起作用的方式:

  1. 创建数据容器以在机器 A 上保存一些持久数据
  2. 创建使用数据容器中的卷的应用程序容器
  3. 做一些工作,可能会改变数据容器中的数据
  4. 停止应用程序容器
  5. 提交并标记数据容器
  6. 将数据容器推送到(私有)存储库
  7. 在机器 B 上拉取并运行第 6 步中的映像
  8. 从你在机器 B 上停下的地方开始

这里的关键步骤是第 5 步,我认为它会保存当前状态(包括文件系统的内容)。然后,您可以将该状态推送到存储库并从其他地方提取它,从而为您提供一个与原始容器基本相同的新容器。

但它似乎不是这样工作的。我发现要么第 5 步没有做我认为的那样,要么第 7 步(拉取和运行图像)将容器“重置”到它的初始状态。

我把一组三个 Docker 镜像和容器放在一起来测试这个:一个数据容器,一个每 30 秒将一个随机字符串写入数据容器中的文件的写入器,以及一个读取echo数据中的值的读取器容器文件并退出。

数据容器

创建于

docker run \
    --name datatest_data \
    -v /datafolder \
    myrepository:5000/datatest-data:latest
Run Code Online (Sandbox Code Playgroud)

Dockerfile:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /datafolder

# write something to the data file
#
RUN echo "no data here!" > /datafolder/data.txt

# expose the data folder
#
VOLUME /datafolder
Run Code Online (Sandbox Code Playgroud)

作家

创建于

docker run \
    --rm \
    --name datatest_write \
    --volumes-from datatest_data \
    myrepository:5000/datatest-write:latest
Run Code Online (Sandbox Code Playgroud)

Dockerfile:

FROM ubuntu:trusty

# Add script
#
ADD run.sh /usr/local/sbin/run.sh
RUN chmod 755 /usr/local/sbin/*.sh

CMD ["/usr/local/sbin/run.sh"]
Run Code Online (Sandbox Code Playgroud)

运行文件

#!/bin/bash

while :
do
    sleep 30s

    NEW_STRING=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

    echo "$NEW_STRING" >> /datafolder/data.txt

    date >> /datafolder/data.txt

    echo "wrote '$NEW_STRING' to file"
done
Run Code Online (Sandbox Code Playgroud)

此脚本/datafolder/data.txt在数据容器中写入一个随机字符串和日期/时间。

读者

创建于

docker run \
    --rm \
    --name datatest_read \
    --volumes-from datatest_data \
    myrepository:5000/datatest-read:latest
Run Code Online (Sandbox Code Playgroud)

Dockerfile:

FROM ubuntu:trusty

# Add scripts
ADD run.sh /run.sh
RUN chmod 0777 /run.sh

CMD ["/run.sh"]
Run Code Online (Sandbox Code Playgroud)

运行.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"
Run Code Online (Sandbox Code Playgroud)

当我构建和运行这些容器时,它们运行良好并按我期望的方式工作:

在开发机器上停止和启动:

  1. 创建数据容器
  2. 运行作家
  3. 立即运行阅读器,看到“这里没有数据!” 信息
  4. 等一会儿
  5. 运行阅读器,看到随机字符串
  6. 阻止作者
  7. 重新启动写入器
  8. 运行阅读器,看到相同的随机字符串

但是承诺和推动不符合我的预期:

  1. 创建数据容器
  2. 运行作家
  3. 立即运行阅读器,看到“这里没有数据!” 信息
  4. 等一会儿
  5. 运行阅读器,看到随机字符串
  6. 阻止作者
  7. 提交并标记数据容器 docker commit datatest_data myrepository:5000/datatest-data:latest
  8. 推送到存储库
  9. 删除所有容器并重新创建它们

在这一点上,我希望运行阅读器并看到相同的随机字符串,因为数据容器已经提交,推送到存储库,然后从存储库中的相同图像重新创建。然而,我实际看到的是“这里没有数据!” 信息。

有人可以解释我在这里出错的地方吗?或者,给我指出一个如何使用 Docker 完成部署的示例?

Tho*_*eil 24

您对 docker 中的卷如何工作有一个错误的假设。我将尝试解释卷与 docker 容器和 docker 镜像的关系,并希望数据卷数据卷容器之间的差异变得清晰。

首先让我们回忆几个定义

Docker 镜像

Docker 镜像本质上是一个联合文件系统 + 元数据。您可以使用该docker export命令检查 docker image union 文件系统的内容,也可以使用该命令检查 docker image 元数据docker inspect

数据量

来自Docker 用户指南

数据卷是一个或多个容器中专门指定的目录,它绕过联合文件系统,为持久或共享数据提供多种有用的功能。

重要的是要注意,给定的卷(作为包含数据的目录或文件)只有在至少存在一个使用它的 docker 容器时才能重用。Docker 镜像没有卷,它们只有元数据,这些元数据最终会告诉卷将安装在联合文件系统上的哪个位置。数据量既不是 docker 容器联合文件系统的一部分,那么它们在哪里呢?在/var/lib/docker/volumesdocker 主机上(而容器存储在 下/var/lib/docker/containers)。

数据量容器

这种特殊类型的容器没有什么特别之处。它们只是使用数据量的停止容器,其唯一且独特的目标是让至少一个容器使用该数据量。请记住,一旦使用给定数据卷的最后一个容器(运行或停止)被删除,该卷将无法通过docker run --volumes-from选项访问。

使用数据卷容器

如何创建数据卷容器

用于创建数据卷容器的映像并不重要,因为这样的容器可以保持停止状态并仍然满足其用途。因此,要创建以datatest_data卷命名的数据容器,/datafolder您只需要运行:

docker run --name datatest_data --volume /datafolder busybox true
Run Code Online (Sandbox Code Playgroud)

base是图像名称(一个方便的小名称),true是我们提供的一个命令,只是为了避免看到 docker 守护进程抱怨缺少命令。无论如何,在您拥有一个以datatest_data允许您使用命令--volumes-from选项到达该卷的唯一目的的已停止容器之后docker run

如何从数据卷容器中读取

我知道两种读取数据量的方法:第一种是通过容器。如果您无法在现有容器中使用 shell 来访问该数据卷,您可以运行一个新容器,该容器--volumes-from的唯一目的是读取该数据。

例如:

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt
Run Code Online (Sandbox Code Playgroud)

另一种方法是从/var/lib/docker/volumes文件夹复制卷。您可以通过检查使用卷的容器之一的元数据来发现该文件夹中卷的名称。有关详细信息,请参阅此答案

处理卷(自 Docker 1.9.0 起)

如何创建卷(自 Docker 1.9.0 起)

Docker 1.9.0 引入了一个docker volume允许创建卷的新命令:

docker volume create --name hello
Run Code Online (Sandbox Code Playgroud)

如何从卷中读取(自 Docker 1.9.0 起)

假设您创建了一个名为hellowith的卷docker volume create --name hello,您可以使用以下-v选项将其安装在容器中:

docker run -v hello:/data busybox ls /data
Run Code Online (Sandbox Code Playgroud)

关于提交和推送容器

现在应该很清楚,由于数据卷不是容器(联合文件系统)的一部分,提交容器以生成新的 docker 映像不会保留数据卷中的任何数据。

备份数据卷

docker 用户指南有一篇关于备份数据卷的好文章。


关于卷的好文章:http ://container42.com/2014/11/03/docker-indepth-volumes/