【问题标题】:Docker: adding a file from a parent directoryDocker:从父目录添加文件
【发布时间】:2014-08-23 14:40:42
【问题描述】:

在我的Dockerfile 我有:

ADD ../../myapp.war /opt/tomcat7/webapps/

该文件存在,因为ls ../../myapp.war 返回了正确的文件,但是当我执行sudo docker build -t myapp . 时,我得到了:

Step 1 : ADD ../../myapp.war /opt/tomcat7/webapps/
2014/07/02 19:18:09 ../../myapp.war: no such file or directory

有人知道为什么以及如何正确地做到这一点吗?

【问题讨论】:

标签: docker


【解决方案1】:

您可以从父目录构建 Dockerfile:

docker build -t <some tag> -f <dir/dir/Dockerfile> .

【讨论】:

  • 谢谢!这在本地机器上运行良好,但 Docker Hub 无法构建映像,因为它试图从其同一目录中进行构建(tbh,这正是人们通常所期望的)。有没有办法在 Docker Hub 中做同样的事情?
  • 我不知道。您可以将图像推送到注册表,而不是使用自动构建。
  • @eduncan911 在我撰写评论时,我认为这并没有被弃用。从那以后他们可能改变主意了?如果我错了,您能否链接到它说它已被弃用的文档。谢谢!
  • -f doesn't 根据文档似乎已被弃用 -> 指定 Dockerfile (-f)docs.docker.com/engine/reference/commandline/build/…跨度>
  • @eduncan911 你可以删除你的评论,因为它显然没有被弃用吗?由于您的评论,我最初跳过了这个答案。
【解决方案2】:

使用 docker-compose,您可以设置上下文文件夹:

#docker-compose.yml
version: '3.3'    
services:
      yourservice:
        build:
          context: ./
          dockerfile: ./docker/yourservice/Dockerfile

【讨论】:

  • 小心设置上下文的位置,因为大文件/文件夹会使进程挂起。您将希望使用 .dockerignore 忽略它们,并更恰当地将您的上下文设置为您真正需要它的点。
  • 使用 docker-compose 作为快捷方式来解决这个上下文构建的问题,目前反正也不错。
  • dockerfile 路径应该是相对于新上下文还是相对于 docker compose 文件?
【解决方案3】:

不幸的是,(我猜是出于实用和安全原因),如果你想添加/复制本地内容,它必须位于与Dockerfile 相同的根路径下。

来自the documentation

路径必须在构建的上下文中;你 无法添加 ../something/something,因为 docker 的第一步 build 是将上下文目录(和子目录)发送到 码头工人守护进程。

编辑: 现在有一个选项 (-f) 可以设置 Dockerfile 的路径;它可用于实现您想要的,请参阅@Boedy 的回复。

【讨论】:

  • 是否有“干净”的解决方法?我不想仅仅为了适应这个而重组我的整个项目目录。
  • 正如@Günter 所说,这里有一个解决方法superuser.com/a/842690/136024 ...它真的“干净”吗?好吧,至少这是一种“解决方法”:)
  • 查看@Boedy stackoverflow.com/a/34300129/2950621的更好答案
  • 这就是我的COPY 失败的原因吗? COPY /Users/miranda9/ /miranda9...是的: 路径必须在构建的上下文中;你不能 COPY ../something /something,因为 docker build 的第一步是将上下文目录(和子目录)发送到 docker 守护进程。
【解决方案4】:

添加一些代码 sn-ps 以支持接受的答案。

目录结构:

setup/
 |__docker/DockerFile
 |__target/scripts/<myscripts.sh>
src/
 |__<my source files>

Docker 文件入口:

RUN mkdir -p /home/vagrant/dockerws/chatServerInstaller/scripts/
RUN mkdir -p /home/vagrant/dockerws/chatServerInstaller/src/
WORKDIR /home/vagrant/dockerws/chatServerInstaller

#Copy all the required files from host's file system to the container file system.
COPY setup/target/scripts/install_x.sh scripts/
COPY setup/target/scripts/install_y.sh scripts/
COPY src/ src/

用于构建 docker 镜像的命令

docker build -t test:latest -f setup/docker/Dockerfile .

【讨论】:

  • 很棒的方法。是否也可以分享install_x.sh的代码?
  • 我不明白-f setup/docker/Dockerfile 标志在做什么。在您的示例中它在做什么?
  • 如果您已经指定了构建上下文和 Dockerfile 的路径,为什么 docker 命令还需要最后一个点?
  • 您也是从哪里运行 docker build 命令的? pwd 是什么?
  • @CharlieParker - -f 选项指定Dockerfile wrt 当前工作目录的相对路径。末尾的点指定当前工作目录。我的回答已经描述了当前工作目录的样子。希望能为您澄清。
【解决方案5】:

由于-f引起了另一个问题,我开发了另一个解决方案。

  • 在父文件夹中创建基础映像
  • 添加了所需的文件。
  • 将此图像用作后代文件夹中项目的基础图像。

-f 标志并没有解决我的问题,因为我的 onbuild 图像在文件夹中查找文件并且必须像这样调用:

-f foo/bar/Dockerfile foo/bar

而不是

-f foo/bar/Dockerfile .

另请注意,这只是-f标志的某些情况的解决方案

【讨论】:

  • 聪明的主意!多阶段构建以传递您需要的文件!感谢分享!
【解决方案6】:

使用 composer 的解决方案是使用 volume 指向父文件夹:

#docker-composer.yml

foo:
  build: foo
  volumes:
    - ./:/src/:ro

但我很确定可以使用volumes in Dockerfile

【讨论】:

  • 不能。 注意:主机目录本质上是依赖于主机的。出于这个原因,您不能从 Dockerfile 挂载主机目录,因为构建的映像应该是可移植的。主机目录不会在所有潜在主机上都可用。 docs.docker.com/engine/tutorials/dockervolumes/…
【解决方案7】:

如果您使用的是 skaffold,请使用 'context:' 指定每个图像 dockerfile 的上下文位置 - 上下文:../../../

            apiVersion: skaffold/v2beta4
            kind: Config
            metadata:
                name: frontend
            build:
                artifacts:
                    - image: nginx-angular-ui
                      context: ../../../
                      sync:
                          # A local build will update dist and sync it to the container
                          manual:
                              - src: './dist/apps'
                                dest: '/usr/share/nginx/html'
                      docker:
                          dockerfile: ./tools/pipelines/dockerfile/nginx.dev.dockerfile
                    - image: webapi/image
                      context: ../../../../api/
                      docker:
                          dockerfile: ./dockerfile
            deploy:
                kubectl:
                    manifests:
                        - ./.k8s/*.yml

skaffold 运行 -f ./skaffold.yaml

【讨论】:

    【解决方案8】:
    • build 来自上层目录的img

    • 为图片命名

    • 启用适当的卷共享

    • 查看上面链接中的 Makefile 以了解如何启动容器...

      docker build . -t proj-devops-img --no-cache --build-arg UID=$(shell id -u) --build-arg GID=$(shell id -g) -f src/docker/devops/Dockerfile
      

    【讨论】:

      【解决方案9】:

      假设你的目录树是这样的:

      dir0
      ├───dir1
      │   └───dir11
      |   |   └───dockerfile
      |   └───dir12 (current)
      └───dir2 (content to be copied)
      

      你的 dockerfile 看起来像这样:

      FROM baseImage
      COPY / /content
      

      假设您想使用 dir11dockerfileCOPYADDdir2 内容复制到新的 docker 映像中> 而你的当前目录dir12

      您必须运行此命令才能正确构建映像:

      docker build -t image-name:tag -f ../dir11/dockerfile ../../dir2
      
      • -t your-image-name 名称和可选的“名称:标签”格式的标签
      • -f ../dir11/dockerfile Dockerfile 的名称(默认为 'PATH/Dockerfile')
      • ../../dir2 COPY 或 ADD 命令的当前路径

      更新

      假设你错误地运行了这个:

      docker build -t image-name:tag -f ../dir11/dockerfile ../../
      

      这不会解决您的问题,因为在这种情况下,COPY / /content 看起来像是在复制 dir0 内容(dir1 和 dir2),所以为了解决这个问题,您可以使用正确的路径,或者您也可以像这样更改 dockerfile 中的 COPY 源路径:

      COPY /dir2 /content
      

      【讨论】:

        猜你喜欢
        • 2013-05-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-31
        • 2020-04-27
        • 2013-05-22
        • 1970-01-01
        • 2012-10-31
        相关资源
        最近更新 更多