Docker gotcha with building a Dockerfile in sub directory

02 March 2018   1 comment   Docker

tl;dr; Watch out for .dockerignore causing no such file or directory when building Docker images

First I tried to use docker-compose:

▶ docker-compose build ui
Building ui
Step 1/8 : FROM node:9
 ---> 29831ba76d93
Step 2/8 : ADD ui/package.json /package.json
ERROR: Service 'ui' failed to build: ADD failed: stat /var/lib/docker/tmp/docker-builder079614651/ui/package.json: no such file or directory

What the heck? Did I typo the name in the ui/Dockerfile?

The docker-compose.yml directive for this was:

yaml
  ui:
    build:
      context: .
      dockerfile: ui/Dockerfile
    environment:
      - NODE_ENV=development
    ports:
      - "3000:3000"
      - "35729:35729"
    volumes:
      - $PWD/ui:/app
    command: start

I don't know if it's the awesomest way to do docker-compose but I did copy this exactly from a different (working!) project. That other project called the web stuff frontend instead of ui in this project.

The Dockerfile looked like this:

FROM node:9

ADD ./ui/package.json ./
ADD ./ui/package-lock.json ./

RUN npm install

EXPOSE 3000
EXPOSE 35729

CMD [ "npm", "start" ]

Let's try without docker-compose. Or rather, do with docker what docker-compose does for me automatically.

▶ docker build ui -f ui/Dockerfile
Sending build context to Docker daemon  158.2MB
Step 1/8 : FROM node:9
 ---> 29831ba76d93
Step 2/8 : ADD ui/package.json /package.json
ADD failed: stat /var/lib/docker/tmp/docker-builder001494654/ui/package.json: no such file or directory

So I thought I perhaps have misunderstood how relative paths worked. I tried EVERYTHING!

I tried changing to docker build . -f ui/Dockerfile. No luck.

I tried all sorts of combinations of this with also changing the line to ADD ui/package.json ... or ADD /ui/package.json ... or ADD ./package.json ... or ADD package.json .... Nothing worked.

Finally I got it to work by doing

▶ cd ui
▶ docker build . -f Dockerfile

but for that to work I had to remove all references of the directory name ui in the Dockerfile. Nice, but this is not going to work in docker-compose.yml since that starts outside the directory ./ui/.

Sigh!

So then I learned about contexts in docker. Well, I skimmed the docs rapidly. To keep things clean it's a good idea to do things within the directory that matters. So I made this change in the docker-compose.yml:

  ui:
    build:
      context: ui
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=development
    ports:
      - "3000:3000"
      - "35729:35729"
    volumes:
      - $PWD/ui:/app
    command: start

(Note the build.context: and build.dockerfile:)

Still doesn't work! 😫 Still various variations of no such file or directory.

The solution

Turns out, in projectroot/.dockerignore it had ui/ as a line entry!!!

I believe this project used to do some of the Python stuff with Docker and the React web app was done "locally" on the host. And since the ui/node_modules directory is so huge someone decided it was smart of avoid Docker mounting that.

Now the .dockerignore has .ui/node_modules and now everything works. I can build it with plain docker and docker-compose from outside the directory.

Perhaps I should have spent the time I spent writing this blog post to instead file a structured GitHub issue on Docker itself somewhere. I.e. that it should have warned be better. Any takers?

Comments

sm

that post just saved me!
completely forgot about the .dockerignore someone had put in our repo!!!!
THANKS!

Your email will never ever be published

Related posts

Previous:
How to throttle AND debounce an autocomplete input in React 01 March 2018
Next:
Now using minimalcss 12 March 2018
Related by Keyword:
When Docker is too slow, use your host 11 January 2018
How to create-react-app with Docker 17 November 2017
Yet another Docker 'A ha!' moment 05 November 2017
"No space left on device" on OSX Docker 03 October 2017