skip to Main Content

I’ve got the following Dockerfile for a React app and I’m running tests after I build this container. This is my first day with Docker and I’m following a course, so not really sure what I’m doing.

FROM node:13.12.0-alpine as builder

WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
RUN npm run build

FROM nginx

RUN apt-get update && apt-get install -y npm
ARG NODE_VERSION=14
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - 
  && apt-get update 
  && apt-get autoremove 
  && apt-get install -y nodejs

COPY --from=builder /app/build /usr/share/nginx/html

The reason I have these two RUN after FROM nginx is that after running docker build -t username/project-name ., I’d run docker run ID npm run test and get /docker-entrypoint.sh: 38: exec: npm: not found.

Since I added the two RUN statements (which I’m not sure is a good idea) the build is still successful, but then I run the tests with docker run ID npm run test and I get the following error:

npm ERR! code ENOENT
npm ERR! syscall open
npm ERR! path /package.json
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, open '/package.json'
npm ERR! enoent This is related to npm not being able to find a file.

I’ve also tried running docker run -w /app ID npm run test but get the ENOENT: no such file or directory, open '/app/package.json' error.

My file structure is this:

project
  node_modules
  src
  Dockerfile
  package.json
  ...

2

Answers


  1. This is an multi-stage build.

    docker build -t username/project-name . creates a container from the last stage starting with from nginx. In this container you copy the build directory but no package.json.

    To solve this problem you could do the following

    1. Run the test in the docker build in container builder. To do this add in the Dockerfile the following line RUN npm run test
    2. Create the builder container with docker build --target=builder -t username/project-name and use docker run ID npm run test
    3. Copy all sources and project data to your last stage, but this is not recommended
    Login or Signup to reply.
  2. The overall multi-stage build pattern you show here is typical for producing a deployable image with a browser-based application compiled down to static files. The entire contents of the image are the last stage, starting from the final FROM line:

    FROM nginx
    # You would not typically reinstall Node here
    # Only copy in the prebuilt files
    COPY --from=builder /app/build /usr/share/nginx/html
    # EXPOSE, CMD, etc. from base nginx image
    

    So this image only contains the contents of the ./build tree from the first stage and nothing else. The package.json file and the node_modules tree aren’t part of this.

    There’s no rule that you must use exclusively Docker-based tools, even if you’re eventually shipping a Docker image. For day-to-day development I’d recommend using a host-based Node environment, rather than trying to indirectly use Docker to simulate it. Then you can run your unit tests before you package up your application.

    # Work on code
    $EDITOR src/main.js
    # Run tests (without involving Docker)
    npm run test
    # Run a local (non-Docker) dev server and make sure it works
    npm run start
    # It works?  Build a minimal nginx-based Docker image and ship it
    docker build -t my/frontend-app:20210511 .
    docker run -p 8888:80 my/frontend-app:20210511
    docker push my/frontend-app:20210511
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search