首页 文章

如何在Docker的构建上下文之外包含文件?

提问于
浏览
218

如何使用Docker文件中的“ADD”命令包含Docker构建上下文之外的文件?

从Docker文档:

路径必须位于构建的上下文中;你不能添加../something/something,因为docker构建的第一步是将上下文目录(和子目录)发送到docker守护程序 .

我不想重构我的整个项目只是为了适应Docker这个问题 . 我想将所有Docker文件保存在同一个子目录中 .

此外,似乎Docker还没有(也可能不会)支持符号链接:Dockerfile ADD command does not follow symlinks on host #1676.

我能想到的唯一另一件事是包含一个预构建步骤,将文件复制到Docker构建上下文中(并配置我的版本控制以忽略这些文件) . 还有比这更好的解决方法吗?

8 回答

  • 35

    为此,我经常发现自己使用 --build-arg 选项 . 例如,在Dockerfile中放入以下内容之后:

    ARG SSH_KEY
    RUN echo "$SSH_KEY" > /root/.ssh/id_rsa
    

    你可以这样做:

    docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .
    
  • 204

    如果您阅读issue 2745中的讨论,不仅docker可能永远不会支持符号链接,他们可能永远不会支持在您的上下文之外添加文件 . 似乎是一种设计理念,即进入docker构建的文件应明确地成为其上下文的一部分,或者来自URL,其中也可能使用固定版本进行部署,以便使用随附的众所周知的URL或文件重复构建 . 码头 Worker 集装箱 .

    我更喜欢使用版本控制源构建 - 即docker build -t stuff http://my.git.org/repo - 否则我将使用随机文件从一些随机位置构建 . 从根本上说,没有.... - SvenDowideit,Docker Inc

    只是我的意见,但我认为你应该重组以分离代码和docker存储库 . 这样容器可以是通用的,并在运行时拉入任何版本的代码而不是构建时间 .

    或者,使用docker作为基本代码部署工件,然后将dockerfile放在代码存储库的根目录中 . 如果你去这条路线可能有意义的是有一个父Docker容器用于更一般的系统级详细信息和一个子容器用于特定于你的代码的设置 .

  • 0

    您还可以首先创建图像所需内容的tarball,并将其用作上下文 .

    https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts

  • 0

    我有一个项目和一些数据文件的相同问题,我无法在回购上下文中移动HIPPA原因 . 我最终使用了2个Dockerfiles . 一个构建主应用程序没有我需要的东西在容器外面并将其发布到内部repo . 然后第二个dockerfile拉出该图像并添加数据并创建一个新图像,然后部署该图像并且永远不会存储在任何地方 . 不理想,但它的目的是保持敏感信息不被回购 .

  • 28

    在Linux上,您可以挂载其他目录而不是对它们进行符号链接

    mount --bind olddir newdir
    

    有关详细信息,请参阅https://superuser.com/questions/842642 .

    我不知道其他操作系统是否有类似的东西可用 . 我还尝试使用Samba共享一个文件夹并将其重新安装到Docker上下文中,该上下文也可以使用 .

  • 3

    我花了很多时间试图找出一个好的模式,以及如何更好地解释这个功能支持正在发生什么 . 我意识到解释它的最好方法如下......

    • Dockerfile:只会在自己的相对路径下看到文件

    • 上下文:"space"中的一个位置,您要共享的文件和Dockerfile将被复制到

    所以,说到这里,这是一个Dockerfile的例子,需要重用一个名为 start.sh 的文件

    Dockerfile

    ALWAYS 将从其相对路径加载,将其自身的当前目录作为对您指定的路径的 local 引用 .

    COPY start.sh /runtime/start.sh
    

    档案

    考虑到这个想法,我们可以考虑为Dockerfiles构建特定内容的多个副本,但它们都需要访问 start.sh .

    ./all-services/
       /start.sh
       /service-X/Dockerfile
       /service-Y/Dockerfile
       /service-Z/Dockerfile
    ./docker-compose.yaml
    

    考虑到这个结构和上面的文件,这里是一个docker-compose.yml

    docker-compose.yaml

    • 在此示例中, shared context dir是 runtime dir .

    • 这里有相同的心理模型,认为这个目录下的所有文件都被移到了所谓的 context .

    • 同样,只需指定要复制到同一目录的Dockerfile . 您可以使用 dockerfile 指定 .

    • 主内容所在的目录是要设置的实际上下文 .

    docker-compose.yml 如下

    version: "3.3"
    services:
    
      service-A
        build:
          context: ./all-service
          dockerfile: ./service-A/Dockerfile
    
      service-B
        build:
          context: ./all-service
          dockerfile: ./service-B/Dockerfile
    
      service-C
        build:
          context: ./all-service
          dockerfile: ./service-C/Dockerfile
    
    • all-service 被设置为上下文,共享文件 start.sh 被复制到那里以及每个 dockerfile 指定的Dockerfile .

    • 每个都以自己的方式构建,共享起始文件!

    干杯!

  • 16

    解决此问题的最佳方法是使用-f独立于构建上下文指定Dockerfile .

    例如,此命令将使ADD命令可以访问当前目录中的任何内容 .

    docker build -f docker-files/Dockerfile .
    

    Update :Docker现在允许将Dockerfile置于构建上下文之外(在18.03.0-ce,https://github.com/docker/cli/pull/886中修复) . 所以你也可以这样做

    docker build -f ../Dockerfile .
    
  • 4

    我相信更简单的解决方法是改变“上下文”本身 .

    所以,例如,而不是给予:

    docker build -t hello-demo-app .
    

    它将当前目录设置为上下文,假设您希望将父目录作为上下文,只需使用:

    docker build -t hello-demo-app ..
    

相关问题