Docker ADD vs VOLUME

时间:2015-01-01 23:31:42

标签: docker

我正在学习Docker,我怀疑何时何地使用ADDVOLUME。以下是我认为这两点的作用:

ADD

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

VOLUME

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

2 个答案:

答案 0 :(得分:150)

ADD

这两者之间的根本区别在于ADD会为您添加的内容做出贡献,无论是文件夹还是实际图像的文件。使用您之后构建的图片的任何人都可以访问您ADD的任何内容。即使您之后删除它也是如此,因为Docker在图层中工作,ADD图层仍然作为图像的一部分存在。要明确的是,在构建时只能ADD某些内容,并且在运行时不能ADD

您想要使用ADD的几个案例:

  • 您希望引用并安装在Dockerfile中的requirements.txt文件中有一些要求。然后,您可以:ADD ./requirements.txt /requirements.txt后跟RUN pip install -r /requirements.txt
  • 您希望将应用程序代码用作Dockerfile中的上下文,例如,如果要将app目录设置为映像中的工作目录,并在映像中运行默认命令实际上运行你的应用程序,你可以这样做:

    ADD ./ /usr/local/git/my_app

    WORKDIR /usr/local/git/my_app

    CMD python ./main.py

VOLUME

另一方面,

卷只允许从映像运行的容器可以访问运行容器的任何本地计算机上的某个路径。您无法使用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
  • 运行容器
  • 您希望容器中的应用可以访问某些本地设置文件。也许这些设置文件在本地计算机上与开发与生产不同。特别是如果那些设置文件是秘密的,在这种情况下你肯定不希望它们在你的图像中。在这种情况下,一个好的策略是将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存在于您希望应用程序运行的所有环境中。

答案 1 :(得分:27)

VOLUME指令在运行时在Docker容器中创建数据卷。作为VOLUME的参数提供的目录是绕过Union File System的目录,主要用于持久和共享数据。

如果您运行docker inspect <your-container>,则会在Mounts部分下方看到Source表示主机上的目录位置,Destination代表在容器中安装目录位置。例如,

"Mounts": [
  {
    "Name": "fac362...80535",
    "Source": "/var/lib/docker/volumes/fac362...80535/_data",
    "Destination": "/webapp",
    "Driver": "local",
    "Mode": "",
    "RW": true,
    "Propagation": ""
  }
]

以下是docker run -v的3个用例:

  1. docker run -v /data:这类似于在Dockerfile中指定VOLUME指令。
  2. docker run -v $host_path:$container_path:这允许您在运行时在容器中将$host_path挂载到$container_path。在开发过程中,这对于在容器上共享主机上的源代码非常有用。在生产中,这可以用于将诸如主机的DNS信息(在/etc/resolv.conf中找到)或秘密之类的东西安装到容器中。相反,您也可以使用此技术将容器的日志写入主机上的特定文件夹。 $host_path$container_path都必须是绝对路径。
  3. docker run -v my_volume:$container_path:这会在$container_path的容器中创建一个数据卷,并将其命名为my_volume。它与使用docker volume create my_volume创建和命名卷基本相同。使用像container data volume这样的多主机存储驱动程序命名这样的卷对于Flocker和共享存储卷非常有用。
  4. 请注意,Dockerfile中没有将主机文件夹作为数据卷安装的方法。引用docker documentation

      

    注意:由于Dockerfile的可移植性和共享目的,因此无法使用它。由于主机目录本质上是依赖于主机的,因此Dockerfile中指定的主机目录可能无法在所有主机上运行。

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