20

I have such folder structure

project
    - config
        -docker
           Dockerfile
           docker-compose.yml
    - src
       here_is_code
    requirements.txt

Dockerfile

FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /code
WORKDIR /code
ADD ../../requirements.txt /code/
RUN pip install -r requirements.txt
ADD src /code/

docker-compose.yml

version: '3'

services:
  web:
    build:
      context: ../../
      dockerfile: config/docker/Dockerfile
    command:
        bash -c "ls"
    volumes:
      - .:/code
    expose:
      - "8000"
  nginx:
    image: nginx
    ports:
    - "8000:8000"
    volumes:
      - .:/code
      - ./config/nginx:/etc/nginx/conf.d
    depends_on:
    - web

When I run docker-compose build I get following error:

Service 'web' failed to build: ADD failed: Forbidden path outside the build context: ../../requirements.txt ()

Is it possible to add requirements.txt or I'll have to copy this file into docker directory? Or maybe I need to use any entrypoint (entrypoint.sh)?

UPDATE

After docker build -f config/docker/Dockerfile . and docker-compose up I can't see my code there. Here is the output of ls -R /code

web_1    | /code:
web_1    | Dockerfile
web_1    | config
web_1    | docker-compose.yml
web_1    | src
web_1    | static
web_1    | 
web_1    | /code/config:
web_1    | nginx
web_1    | 
web_1    | /code/config/nginx:
web_1    | 
web_1    | /code/src:
web_1    | static
web_1    | 
web_1    | /code/src/static:
web_1    | 
web_1    | /code/static:
Lin Du
  • 88,126
  • 95
  • 281
  • 483
Headmaster
  • 2,008
  • 4
  • 24
  • 51
  • 8
    I think if you have `context: ../../` you no longer mean to point to `ADD ../../requirements` but rather `ADD ./requirements`. Or is this file 2 levels above the context `../../`? That is not allowed, you should move the file. – Boris van Katwijk Jan 21 '19 at 09:57
  • @BorisvanKatwijk - right. I've used `ADD ./requirements` and it works – Headmaster Jan 21 '19 at 10:00
  • Possible duplicate of [How to include files outside of Docker's build context?](https://stackoverflow.com/questions/27068596/how-to-include-files-outside-of-dockers-build-context) – David Maze Jan 21 '19 at 11:45

4 Answers4

33

context

It's all about context. Specify context and dockerfile in your build and you can plant your Dockerfile anywhere. Play a round with it (that's what she said).

I would at least keep the docker-compose.yaml in a root directory.


build:
  context: .
  dockerfile: dockerfiles/project-one/Dockerfile

Bicameral Mind
  • 799
  • 5
  • 9
  • 2
    This doesn't work if you want to locate the docker-compose.yaml file in the sub-folder as well. If you have one global docker-compose file, that defeats the purpose of having placing the Dockerfile in a sub-folder. You're then required to use that global docker-compose.yaml file for everything, even if you want to describe separate container collections. – Cerin May 16 '19 at 21:21
  • 4
    One global docker-compose defeats nothing. – Bicameral Mind Jun 13 '19 at 19:13
  • 3
    Most people are running one docker-compose to build their images straight up. – Bicameral Mind Jun 13 '19 at 19:13
  • 1
    I run multiple micro-services with their own Dockerfile in their respective sub-directories--using one docker-compose to build all the images, or I run docker-compose build to build specific ones. Depends on the service, script, etc that I am applying. There's no need to have multiple docker-compose files along side Dockerfiles. Nobody needs extra docker-compose yamls with however many lines in each, when you can just one-line it in a script using the same docker-compose. – Bicameral Mind Jun 13 '19 at 19:13
  • So yeah, when it comes to context--as that is what the answer is about! It works perfectly. Even if you want to waste time placing extra files in directories that aren't otherwise needed. – Bicameral Mind Jun 13 '19 at 19:13
16

You cannot get outside of build context (which is normally the working directory) of Docker when building an image.

The reason is pretty simple - Docker consists of command line client and daemon, when you call docker build ... first thing happening is that your client packs entire folder (build context) into single archive and sends it to daemon together with your Dockerfile. Daemon gets an archive and instructions from Dockerfile and that means daemon does not access your local filesystem when building an image and cannot walk through ../.. references.

What you need to to set the build context to your root folder and specify Dockerfile explicitly.

You build command will look like

docker build -f config/docker/Dockerfile .

And inside Dockerfile you have to remember that all paths are relative to the project root.

So finally you come to following compose file:

docker-compose.yml

version: '3'
services:
  web:
    build:
      context: .  # here changed
      dockerfile: config/docker/Dockerfile
    command: ["bash", "-c", "ls"]
    expose:
      - "8000"
  nginx:
    image: nginx
    ports:
      - "8000:8000"
    depends_on:
      - web

You go to project root and run

docker-compose -f config/docker/docker-compose.yml up
grapes
  • 8,185
  • 1
  • 19
  • 31
1

Hope, my answer will help somebody (it is based on many GitHub repositories, I have looked though)

I have wrong project structure. If you need to separate docker files and application code, it's better to put the code in any folder (called app for example) in the root folder. Docker files should also be in the root folder. Such structure will avoid a lot of problems and it will be easy to use docker/docker-compose

Headmaster
  • 2,008
  • 4
  • 24
  • 51
1
_______________________________
deployments/docker-compose.yml:
[...]
service_name:
  build:
      context: ..                           # *That's what you need!*
      dockerfile: build/package/Dockerfile

_________________________
build/package/Dockerfile:
[...]
COPY . .

_____________________
from root of project:

docker-compose -f deployments/docker-compose.yml up

And your container will have everything from the root of a project.

sav4ik
  • 11
  • 1