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


18

首先,我承认我是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

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

作家

创建于

docker run \
    --rm \
    --name datatest_write \
    --volumes-from datatest_data \
    myrepository:5000/datatest-write:latest

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"]

运行

#!/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

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

读者

创建于

docker run \
    --rm \
    --name datatest_read \
    --volumes-from datatest_data \
    myrepository:5000/datatest-read:latest

Dockerfile:

FROM ubuntu:trusty

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

CMD ["/run.sh"]

run.sh:

#!/bin/bash

echo "reading..."

echo "-----"

cat /datafolder/data.txt

echo "-----"

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

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

  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进行部署的示例?

Answers:


22

您对卷在docker中的工作方式有一个错误的假设。我将尝试解释卷与Docker容器和Docker映像之间的关系,并希望数据卷数据卷容器之间的区别将变得清晰。

首先让我们回顾一些定义

Docker映像

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

数据量

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

base是映像名称(一个小巧的名称),这true是我们提供的命令,目的是避免看到docker daemon抱怨缺少命令。无论如何,在一个已停止的容器命名后datatest_data,其唯一目的是允许您--volumes-from通过docker run命令选项达到该卷。

如何从数据卷容器中读取

我知道两种读取数据量的方法:第一种是通过容器。如果无法在现有容器中添加外壳来访问该数据量,则可以运行带有--volumes-from选项的新容器,其唯一目的是读取该数据。

例如:

docker run --rm --volumes-from datatest_data busybox cat /datafolder/data.txt

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

使用卷(自Docker 1.9.0起)

如何创建卷(自Docker 1.9.0起)

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

docker volume create --name hello

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

比方说您创建了一个名为体积hellodocker volume create --name hello,你可以用一个容器安装它-v的选项:

docker run -v hello:/data busybox ls /data

关于提交和推送容器

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

备份数据量

docker用户指南上有一篇不错的文章,介绍如何进行数据卷备份


好的文章阅读量:http ://container42.com/2014/11/03/docker-indepth-volumes/


似乎“用于创建数据卷容器的映像不重要”并不完全正确。只需尝试使用一个“临时”映像,它将为您提供“ exec:“ true”:找不到可执行文件”
tcurdt 2014年

尽管有此错误,您的容器仍将被创建为发挥其容量持有者的作用
Thomasleveil 2014年

1
嗯-也许值得为此提出一个问题。
tcurdt

不,该行为是预期的,因为暂存图像是空图像,/bin/true无论如何都不能具有二进制(或任何其他图像)
Thomasleveil 2014年

1
就一件事。您说过:“一旦删除了使用给定数据量的最后一个容器(正在运行或已停止),docker就会从/ var / lib / docker / volumes中销毁该数据量。”,但实际上并非如此:请看:docs.docker.com/userguide/dockervolumes(即使删除容器本身,数据卷也会保留。您必须docker rm -v针对最后一个容器指定命令才能删除卷)
juanra

1

您还可以使用Docker数据容器来部署代码

我不知道这是否是一个好习惯,但是我这样做是这样的:

FROM ubuntu:trusty

# make the data folder
#
RUN mkdir /data-image

# in my case, I have a 
# ADD dest.tar /data-image/
#
# but to follow your example :
# write something to the data file
RUN echo "no data here!" > /data-image/data.txt

# expose the data folder 
#
VOLUME /datafolder

ENTRYPOINT cp -r /data-image/* /datafolder/

现在,您可以推送图像并使用volume-from等等。


这就是我要寻找的,但是被接受的答案明确提到了这不能完成。现在要尝试一下。
andho

1
乍一看,可接受的答案表示不会提交卷(或其中的数据),但是您可以使用COPY或在Dockerfile 中使用将数据添加到容器中ADD并创建卷VOLUME
andho
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.