3

I have an NodeJS express app that I want to dockerize. For that I created a Dockerfile:

FROM node:18 AS server
ENV NODE_ENV=production
WORKDIR /app
COPY package*.json /
RUN npm ci
COPY . .

I also have a .dockerignore file:

node_modules/
client/node_modules/

Dockerfile
docker-compose.yml
.git
.gitignore
.dockerignore
.env

All is run with a help of docker-compose.yml:

version: '3.8'
services:
  app:
    container_name: my-app
    image: my-org/my-app
    build:
      context: .
      dockerfile: Dockerfile
    command: node index.js
    ports:
      - "3030:3030"
    environment:
      HELLO: world
    env_file:
      - .env

When I run the Dockerfile commands in this order, the COPY . . seems to remove the node_modules from the image, that are created with npm ci that runs beforehand. I've tried it with first running COPY . . and then npm ci and node_modules stays in the image.

My question is – is it better to run npm ci before COPY . ., and if the answer is yes, then how can I make the node_modules stay?

mdmb
  • 4,833
  • 7
  • 42
  • 90
  • 2
    You have "node_modules/" in your .dockerignore. How do you expect to copy it into your image? – Marc Aug 09 '22 at 17:28
  • remove node_modules from .dockerignore – Mahmoud Kassem Aug 09 '22 at 17:40
  • I think [Why COPY package*.json ./ precedes COPY . .?](https://stackoverflow.com/questions/51533448/why-copy-package-json-precedes-copy) is one of your questions (yes, it's better to `RUN npm ci` before `COPY ./ ./`, because rebuilds will be faster). But since you exclude `node_modules` in your `.dockerignore` file I would not expect it to wipe out the result of that installation. How do you verify that it is or isn't there? – David Maze Aug 09 '22 at 18:07
  • (Contrary to other commenters, you _should_ include `node_modules` in `.dockerignore`, since the container may be a different OS or Linux distribution from the host system; you do not want the host's `node_modules` tree here.) – David Maze Aug 09 '22 at 18:08

1 Answers1

0

I had a similar problem and used for that a "build container".

You ignored the node_modules folder in your .dockerignore. Therfore it does not get copied in your image.

# The instructions for the first stage
FROM node:16-alpine as builder

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

RUN apk --no-cache add python3 make g++

COPY ./package*.json ./
RUN npm install


# ------------------------------------


# The instructions for second stage
FROM node:16-alpine

WORKDIR /opt/OpenHaus/backend
COPY --from=builder node_modules node_modules
RUN apk --no-cache add openssl

COPY . ./
#COPY ./package.json ./

#ENV HTTP_PORT=8080
ENV NODE_ENV=production
#ENV DB_HOST=10.0.0.1
#EXPOSE 8080

CMD ["node", "index.js"]

With that the dependencies are "build" and copied from the build container inside your node.js image.

More to read:

Marc
  • 2,920
  • 3
  • 14
  • 30