Docker添加与卷 ADD vs VOLUME

Docker ADD vs VOLUME

我正在学习docker,我对何时何地使用ADDVOLUME表示怀疑。以下是我认为这两种方法的作用:

添加

在生成时将文件复制到映像。映像包含所有文件,因此您可以非常轻松地部署。另一方面,在开发中,每次都需要构建看起来并不是一个好主意,因为构建需要开发人员运行一个命令来重建容器;此外,构建容器可能非常耗时。

体积

我了解到,使用docker run -v,您可以在容器中装入一个主机文件夹,这样您就可以轻松地修改文件并观察容器中的应用程序对更改的反应。它在开发中看起来很好,但我不确定如何以这种方式部署我的文件。


添加

这两者之间的根本区别在于,ADD可以制作您添加的任何内容,无论是文件夹还是文件,实际上都是图像的一部分。任何使用您之后创建的图像的人都可以访问您的ADD。这是真的,即使您后来删除它,因为docker工作在层和ADD层仍将作为图像的一部分存在。很明显,您在构建时只使用ADD的东西,在运行时不能使用ADD

您希望使用ADD的几个示例:

  • 在requirements.txt文件中,您有一些需要要参考并安装在dockerfile中。你可以这样做:ADD ./requirements.txt /requirements.txt,接着是RUN pip install -r /requirements.txt
  • 您希望在Dockerfile中使用应用程序代码作为上下文,例如,如果您希望将应用程序目录设置为图像中的工作目录,并希望从图像中运行容器中的默认命令来实际运行应用程序,可以执行以下操作:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

体积

另一方面,卷只允许从映像运行的容器访问运行容器的任何本地计算机上的某个路径。您不能使用dockerfile中的VOLUME目录中的文件。卷目录中的任何内容在生成时都无法访问,但在运行时可以访问。

您希望使用VOLUME的几个示例:

  • 在容器中运行的应用程序在/var/log/my_app中生成日志。您希望可以在主机上访问这些日志,并且在删除容器时不删除这些日志。您可以通过在/var/log/my_app上创建一个挂载点来实现这一点,方法是将VOLUME /var/log/my_app添加到dockerfile,然后使用docker run -v /host/log/dir/my_app:/var/log/my_app some_repo/some_image:some_tag运行容器。
  • 您有一些本地设置文件希望容器中的应用程序可以访问。也许这些设置文件在本地计算机上与dev和production上是不同的。尤其是如果这些设置文件是秘密的,在这种情况下,您肯定不希望它们出现在您的图像中。在这种情况下,一个好的策略是将VOLUME /etc/settings/my_app_settings添加到dockerfile,使用docker run -v /host/settings/dir:/etc/settings/my_app_settings some_repo/some_image:some_tag运行容器,并确保/host/settings/dir存在于您希望运行应用程序的所有环境中。


VOLUME指令在运行时在Docker容器中创建数据卷。作为VOLUME的参数提供的目录是一个绕过联合文件系统的目录,主要用于持久和共享数据。

如果运行docker inspect ,您将看到在Mounts部分下面有一个Source,表示主机上的目录位置,还有一个Destination,表示容器中装入的目录位置。例如,

1
2
3
4
5
6
7
8
9
10
11
"Mounts": [
  {
   "Name":"fac362...80535",
   "Source":"/var/lib/docker/volumes/fac362...80535/_data",
   "Destination":"/webapp",
   "Driver":"local",
   "Mode":"",
   "RW": true,
   "Propagation":""
  }
]

这里有3个docker run -v的用例:

  • docker run -v /data:这类似于在dockerfile中指定VOLUME指令。
  • docker run -v $host_path:$container_path:这允许您在运行时将$host_path从主机安装到容器中的$container_path。在开发中,这对于在主机上与容器共享源代码很有用。在生产中,这可以用于将主机的DNS信息(在/etc/resolv.conf中找到)或机密等内容装入容器中。相反,您也可以使用此技术将容器的日志写入主机上的特定文件夹中。$host_path$container_path都必须是绝对路径。
  • docker run -v my_volume:$container_path:这会在$container_path的容器中创建一个数据卷,并将其命名为my_volume。它本质上与使用docker volume create my_volume创建和命名卷相同。使用类似Flocker的多主机存储驱动程序命名这样的卷对于容器数据卷和共享存储卷很有用。
  • 请注意,在DockerFile中,将主机文件夹装入数据卷的方法不可用。引用Docker文档,

    Note: This is not available from a Dockerfile due to the portability and sharing purpose of it. As the host directory is, by its nature, host-dependent, a host directory specified in a Dockerfile probably wouldn't work on all hosts.

    现在,如果要将文件复制到非开发环境中的容器中,可以在dockerfile中使用ADDCOPY指令。这些是我通常用于非开发部署的。