reactjsdockerwebpackdocker-compose

Can't build react app in docker in production environment


I'm trying to build a react docker image with NODE_ENV set to production, but keep getting this error:

#0 11.74 > webpack --config webpack-prod.config.ts
#0 11.74 
#0 11.83 CLI for webpack must be installed.
#0 11.83   webpack-cli (https://github.com/webpack/webpack-cli)
#0 11.83 
#0 11.83 We will use "npm" to install the CLI via "npm install -D webpack-cli".
#0 11.83 Do you want to install 'webpack-cli' (yes/no): 

I tried to install webpack-cli separately but can't seem to get it working.

All the guides I've seen seem to say that devDependencies are not needed for the build. Also seems like setting NODE_ENV to production turns on some optimizations, so I wanted to add that. Without NODE_ENV build is running normally, because it adds devDeps I assume.

Am I doing something wrong here or do I need devDeps after all?

Dockerfile:

FROM node:16-alpine as build
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
RUN npm install -g webpack-cli && npm run build

FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf

docker-compose:

version: '3'
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - '80'
    networks:
      - default

package.json scripts:

"build": "webpack --config webpack-prod.config.ts",
"start": "webpack serve --config webpack-dev.config.ts --progress"

Solution

  • You probably need the development dependencies installed to run your local build sequence. This can include things like Webpack, the Typescript transpiler, and other tools that you need to build the application into static files but not necessarily to run it. The package.json "devDependencies": are needed for the build.

    If your npm run build sequence behaves differently in production mode, then you need to set $NODE_ENV after you install the packages from your package.json file.

    FROM node:16-alpine as build
    WORKDIR /app
    COPY package.json package-lock.json ./  # don't forget package-lock.json!
    RUN npm ci                              # including devDependencies
    COPY . .
    ENV NODE_ENV=production                 # only after `npm ci`
    RUN npm run build
    
    FROM nginx:alpine                       # unchanged
    COPY --from=build /app/build /usr/share/nginx/html
    COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
    

    Since you're building a pure Web application, this is enough. The recipe is a little bit more complicated if it's a server-side application: you need to RUN npm ci twice, once including devDependencies in an earlier stage to build the application, and once with NODE_ENV=production when you're actually going to run it.