467

In my Dockerfile I've got :

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

That file exists as ls ../../myapp.war returns me the correct file but when I execute sudo docker build -t myapp . I've got :

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

Does somebody know why and how to do it correctly?

Anthony O.
  • 22,041
  • 18
  • 107
  • 163
  • 3
    Some workarounds http://superuser.com/questions/842642 – Günter Zöchbauer Nov 30 '14 at 19:51
  • 1
    looks like a softlink won't work either: https://superuser.com/questions/842642/how-to-make-a-symlinked-folder-appear-as-a-normal-folder or maybe works with some workarounds mentioned here – Geronimo May 10 '23 at 15:35

12 Answers12

549
  1. cd to your parent directory instead
  2. build the image from the parent directory, specifying the path to your Dockerfile
docker build -t <some tag> -f <dir/dir/Dockerfile> .

In this case, the context of the docker will be switched to the parent directory and accessible for ADD and COPY

Sergey Pleshakov
  • 7,964
  • 2
  • 17
  • 40
Boedy
  • 6,647
  • 1
  • 21
  • 24
  • 5
    Thank you! This works fine on a local box, but Docker Hub fails to build the image since it tries to do it from its same directory (tbh, just what one would normally expect). Is there any way to do the same trick in Docker Hub? – Marcel Hernandez Mar 25 '16 at 20:31
  • Not that I know of. You could push the image to the registry instead of using automated build. – Boedy Mar 29 '16 at 09:15
  • 10
    `-f` *doesn't* appear to be deprecated per the docs -> _Specify a Dockerfile (-f)_: https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f – Ray Jan 24 '18 at 21:29
  • 1
    As I read this bulletin, the '-f' flag has only been deprecated on the 'tag' command - https://docs.docker.com/engine/deprecated/#separator--of---security-opt-flag-on-docker-run – Carter Sanders Feb 22 '18 at 01:09
  • I just ran into something that I thought I might be worth adding. While trying to copy a file from inside a folder named `bin` this error still came up for this command, moving it to folder with a different name allowed it to complete. No idea why. – Geoff Johnson Aug 27 '19 at 19:30
  • Won't *any* changes to files in the parent dir bump the docker versions and force a rebuild though? – mathtick Apr 18 '20 at 16:16
  • you can also do relative path to up folder with ../.. so now you are one level above =) just make sure in your Dockerfile in the copy section that you also start from the same level, that way you can incorporate folder that are outside where the Dockerfile lives – pelos May 05 '21 at 18:53
  • but why doesn't `COPY ../../.. .` work for me - I keep seing the contents of the current directory where I ran docker build? – Charlie Parker Aug 18 '21 at 21:55
  • @Boedy can you give a concrete example? I tried `docker build -t my_img -f /Users/miranda9/repo .` and I still can't get it to work with error: `failed to solve with frontend dockerfile.v0: failed to read dockerfile: error from sender: open /Users/miranda9/.Trash: operation not permitted`. Not sure why its trying to do that...? what is going on? – Charlie Parker Aug 18 '21 at 22:18
  • If anybody comes across the same issue as me, you want to then specify ADD myapp.war /opt/tomcat7/webapps/ rather than ADD ../../myapp.war /opt/tomcat7/webapps/ in the docker file. – GR4 Oct 24 '22 at 16:26
244

With docker-compose, you could set context folder:

# docker-compose.yml

version: '3.3'    
services:
  yourservice:
    build:
      context: ./
      dockerfile: ./docker/yourservice/Dockerfile
Brian Burns
  • 20,575
  • 8
  • 83
  • 77
Nikita Kuznetsov
  • 2,527
  • 1
  • 11
  • 12
  • 9
    Be careful where you set your context to because large files/folders will make the process hang. You'll want to ignore them with .dockerignore and more appropriately set your context to the point where you really need it. – Matt Kenefick Feb 17 '21 at 16:44
  • 1
    Using docker-compose as a shortcut to solve this problem of context build is not bad at the moment anyway. – gia huy May 28 '21 at 16:20
  • 1
    Should dockerfile path be relative to the new context or to docker compose file? – Noname Aug 13 '21 at 04:58
  • 1
    "When the value supplied is a relative path, it is interpreted as relative to the location of the Compose file. " https://docs.docker.com/compose/compose-file/compose-file-v3/ – 00schneider Mar 26 '22 at 16:26
181

Unfortunately, (for practical and security reasons I guess), if you want to add/copy local content, it must be located at the same level in the directory tree as the Dockerfile.

From the documentation:

The <src> path must be inside the context of the build; you cannot ADD ../something/something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon.

EDIT: There's now an option (-f) to set the path of your Dockerfile ; it can be used to achieve what you want, see @Boedy 's response.

jorisw
  • 875
  • 1
  • 11
  • 17
mbarthelemy
  • 12,465
  • 4
  • 41
  • 43
  • 57
    Is there a "clean" workaround for this? I'd rather not restructure my whole project directory just to accommodate this. – ben_frankly Nov 21 '14 at 18:35
  • 1
    As said by @Günter, there is a workaround here http://superuser.com/a/842690/136024 ... is it really "clean"? Well at least it's a "workaround" :) – Anthony O. Dec 02 '14 at 08:39
  • 3
    See better answer from @Boedy http://stackoverflow.com/a/34300129/2950621 – nmgeek Jun 19 '16 at 19:27
  • is this why my `COPY` is failing? `COPY /Users/miranda9/ /miranda9`...yes it is: The path must be inside the context of the build; you cannot COPY ../something /something, because the first step of a docker build is to send the context directory (and subdirectories) to the docker daemon. – Charlie Parker Aug 18 '21 at 22:02
  • 4
    I'd like to hear any "security reason" for this, really – flm Mar 25 '22 at 14:40
  • @flm, here is more information about increasing container isolation and, therefore, possible holes and breaches: https://docs.docker.com/desktop/hardened-desktop/enhanced-container-isolation/features-benefits/ - you might find answer here. – Gleichmut May 02 '23 at 15:14
  • @Boedy response might work for a console execution, but does Docker provide something similar to run from ```docker-compose.yaml```? Upper in comments someone referred rising level up in file hierarchy ```../```, but this gives 'not found` error on the build and, actually, its stays aligned with ```COPY``` behaviour. – Gleichmut May 02 '23 at 15:18
40

Adding some code snippets to support the accepted answer.

Directory structure :

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

Docker file entry:

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/

Command used to build the docker image

docker build -t test:latest -f setup/docker/Dockerfile .
Binita Bharati
  • 5,239
  • 1
  • 43
  • 24
  • great approach. Is it possible to share the code of `install_x.sh` as well? – Ariful Haque Feb 17 '20 at 03:03
  • I don't understand what `-f setup/docker/Dockerfile` flag is doing. What is it doing in your example? – Charlie Parker Aug 18 '21 at 22:27
  • also why does the docker command need the final dot if you are already specifying the path to the build context and Dockerfile? – Charlie Parker Aug 18 '21 at 22:28
  • also from where did you run that docker build command? what is the `pwd`? – Charlie Parker Aug 18 '21 at 22:29
  • @CharlieParker - `-f` option specifies the relative path of the `Dockerfile` wrt current working directory. The dot at the end specifies the current working directory. My answer already depicts how the current working directory looks like. Hope that clarifies it for you. – Binita Bharati Aug 22 '21 at 13:22
16

Since -f caused another problem, I developed another solution.

  • Create a base image in the parent folder
  • Added the required files.
  • Used this image as a base image for the project which in a descendant folder.

The -f flag does not solved my problem because my onbuild image looks for a file in a folder and had to call like this:

-f foo/bar/Dockerfile foo/bar

instead of

-f foo/bar/Dockerfile .

Also note that this is only solution for some cases as -f flag

guneysus
  • 6,203
  • 2
  • 45
  • 47
8

Given the following setup:

+ parent
    + service1
        - some_file.json
    + service2
        - Dockerfile

If you have a Dockerfile in service2 and want to copy some_file.json from service1, you can run this inside the service2 directory:

docker build -t my_image ../ --file Dockerfile

This will set the target context one level above. The tricky part here is that the target Dockerfile is set explicitly (as it is not in the target context).

In service2/Dockerfile, you must issue the COPY command as if the file were one level above:

COPY service1/some_file.json /target/location/some_file.json

instead of

COPY ../service1/some_file.json /target/location/some_file.json # will not work

lfarroco
  • 574
  • 6
  • 14
3

Let's say you have your directories tree like this:

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

and your dockerfile look like this:

FROM baseImage
COPY / /content

Let's say you want to copy dir2 content into a new docker image using COPY or ADD of dockerfile that is in dir11 and your current directory is dir12

You will have to run this command in order to build your image properly:

docker build -t image-name:tag -f ../dir11/dockerfile ../../dir2
  • -t your-image-name Name and optionally a tag in the 'name:tag' format
  • -f ../dir11/dockerfile Name of the Dockerfile (Default is 'PATH/Dockerfile')
  • ../../dir2 path to be current for COPY or ADD commands

Update

Let's say you run this by mistake:

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

This will not solve your problem because in this case the COPY / /content will look like it's copying dir0 content (dir1 & dir2) so in order to fix that you can either change the command using the right path or you can also change the COPY source path in the dockerfile like this:

COPY /dir2 /content
Affes Salem
  • 1,303
  • 10
  • 26
3

Let setting context: ../../ in parent folder in docker-compose.yml
Ex:

app:
    build:
      context: ../../
      dockerfile: ./source/docker/dockerfile/Dockerfile
2

If you are using skaffold, use 'context:' to specify context location for each image dockerfile - context: ../../../

            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 run -f ./skaffold.yaml

Sukhminder Sandhu
  • 696
  • 1
  • 5
  • 6
1
  • build the img from an upper dir

  • name the img

  • enable proper volume sharing

  • check the Makefile in the link above on how-to start the container ...

    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
    
Yordan Georgiev
  • 5,114
  • 1
  • 56
  • 53
0

The solution for those who use composer is to use a volume pointing to the parent folder:

#docker-composer.yml

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

But I'm pretty sure the can be done playing with volumes in Dockerfile.

Pang
  • 9,564
  • 146
  • 81
  • 122
wikier
  • 2,517
  • 2
  • 26
  • 39
  • 7
    It can't. _Note: The host directory is, by its nature, host-dependent. For this reason, **you can’t mount a host directory from Dockerfile** because built images should be portable._ A host directory wouldn’t be available on all potential hosts. https://docs.docker.com/engine/tutorials/dockervolumes/#mount-a-host-directory-as-a-data-volume – Peeter Kokk Jul 08 '16 at 22:23
0

You should not do this bcs the idea is for the build to be portable but if you must:

Instruct Docker to set context: to the parent folder. For example if you have a Documents parent folder with /ssl and /my-proj subfolders you could instruct Docker to copy ssl files to the container like this:

This Docker compose file would be at Documents/my-proj/compose.yaml.

  nginx:
    build:
      context: ../
      dockerfile_inline: |
        FROM nginx:latest
        WORKDIR /etc/nginx
        COPY /ssl/example.com/certificate.crt ssl/
        COPY /ssl/example.com/private.key ssl/
    container_name: nginx
    restart: unless-stopped
    ports: [80:80,443:443,59840:59840]
    volumes:
      - $NGINX_CONF_FILEPATH:/etc/nginx/conf.d/default.conf
Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91