Docker copy react and express package json into same WORKDIR

Issue

I’m new to docker and I have a express server folder with package.json and a client folder with package.json. I have seen many tutorials out there where they have 2 separate images/containers one client and one server. They both have the same WORKDIR

WORKDIR /app
COPY ["package.json", "package-lock.json", "./"]

Does this not override one package.json with the other seen as they are in the same WORKDIR ?

My head is spinning reading different tutorials.
Can someone set me straight here.

This was one of the tutorials I was following which has the same WORKDIR for both client and server https://towardsdatascience.com/deploying-a-react-nodejs-application-with-docker-part-i-of-ii-910bc6edb46e

Solution

Think of images as templates for a system and containers as instances of those templates.

If you and I both bought brand new computers from the same manufacturer, same OS, etc, would /app on mine be the same /app on yours? The answer is of course no.

The WORKDIR is just a directory. It can be helpful if the system you’re creating requires known paths but you can name it literally anything you want, with the exception that you wouldn’t want to copy your app files into a system directory like /etc, /usr, etc.


To address the Express / React app you’re building, I would recommend the following multi-stage Dockerfile to produce a single, production-ised image

## Build stage
FROM node:16-alpine AS build
ENV NODE_ENV=production

WORKDIR /client

COPY client/package*.json ./

RUN npm install

COPY client ./

RUN npm run build

## App stage
FROM node:16-alpine AS app
ENV NODE_ENV=production

WORKDIR /app

COPY server/package*.json ./

RUN npm install

COPY server ./

# Copy the built React app into your static files dir, eg "public"
COPY --from=build /client/build ./public

RUN npm start

For local development, if you want to use Docker I’d recommend this compose setup

# dev.Dockerfile
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
CMD npm start
# docker-compose.yml
version: '3.8'
services:
  client:
    build:
      context: ./client
      dockerfile: ../dev.Dockerfile
    volumes:
      - "./client:/app"
      - "/app/node_modules" # don't overwrite node_modules
    ports:
      - "3000:3000" # adjust accordingly
  server:
    build:
      context: ./server
      dockerfile: ../dev.Dockerfile
    volumes:
      - "./server:/app"
      - "/app/node_modules"
    ports:
      - "5000:5000" # adjust accordingly

Make sure you proxy requests from your React app to the server. In client/package.json, add

"proxy": "http://server:5000"

See this answer to help understand the differences between development and production modes for such an application.

To run it, you simply execute

docker compose up

Then open http://localhost:3000 in your browser. Thanks to the proxy config in dev and having Express serve the files statically in prod, the React app can make requests to your Express API using path-only URLs, eg

axios.post("/api/login", { username, password });

Answered By – Phil

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published