0

Im using docker/docker-compose to get my react (ts) app up and running. The script im currently using works perfectly, on 1 condition. That I've already did 'npm install' inside the directory, while not in docker.

I would like to be able to clone my project from github, and just do docker-compose up, and that it works than.

Right now i first have to run 'npm install', and than 'docker-compose up' for it to work sadly.

I tried just using RUN npm install react-scripts -g, and that kinda works. however i than get a error for typescript, and all other packages.

What I want to be happening is. When I clone my repo, and use docker-compose up. That my whole project runs. It also should make a node_modules folder in my react folder that I can see in my IDE. This is so that my IDE knows the code in the package and doesn't yell at me the whole time.

I cant figure out how to get this to work, I'm already struggling on this for hours and can't find online how to fix it. Hope anyone can help me :D

My structure looks something like this:

  • apps
    • frontend
      • Dockerfile
      • composer.json
      • // All the other react files/folders
  • docker-compose.yml

Dockerfile:

FROM node:16.14.2

WORKDIR /usr/src/app

COPY ./package*.json ./

RUN npm install

CMD npm start --host 0.0.0.0 --port 3000 --disableHostCheck true

docker-compose.yml:

version: '3'

services:
    frontend:
        build:
            context: ./apps/frontend
            dockerfile: ./Dockerfile
        volumes:
            - ./apps/frontend:/usr/src/app
        ports:
            - 3000:3000
        environment:
            - CHOKIDAR_USEPOLLING=true
            - API_BASE_URL=host.docker.internal:8080/api
        extra_hosts:
            - "host.docker.internal:host-gateway"

The error im getting is:

frontend_1  | > [email protected] start
frontend_1  | > react-scripts start "0.0.0.0" "3000"
frontend_1  | 
frontend_1  | sh: 1: react-scripts: not found
cyldiscordbot_frontend_1 exited with code 127

package.json (idk if you need it, but here it is):

{
  "name": "spa",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@cylbot/cyldiscordbotlanguage": "^2.0.3",
    "@emotion/core": "^11.0.0",
    "@emotion/react": "^11.7.1",
    "@emotion/styled": "^11.6.0",
    "@mui/icons-material": "^5.3.1",
    "@mui/material": "^5.5.0",
    "@testing-library/user-event": "^13.2.1",
    "@types/node": "^17.0.9",
    "@types/react": "^17.0.38",
    "@types/react-dom": "^17.0.11",
    "axios": "^0.25.0",
    "emotion-theming": "^11.0.0",
    "enzyme": "^3.11.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-redux": "^7.2.6",
    "react-router-dom": "^6.2.1",
    "react-scripts": "5.0.0",
    "redux": "^4.1.2",
    "redux-saga": "^1.1.3",
    "redux-thunk": "^2.4.1",
    "styled-components": "^5.3.3",
    "typescript": "^4.5.4",
    "web-vitals": "^2.1.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage",
    "storybook": "start-storybook -p 6006 -s public",
    "build-storybook": "build-storybook -s public"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ],
    "overrides": [
      {
        "files": [
          "**/*.stories.*"
        ],
        "rules": {
          "import/no-anonymous-default-export": "off"
        }
      }
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@material-ui/core": "^4.12.3",
    "@storybook/addon-actions": "^6.4.19",
    "@storybook/addon-essentials": "^6.4.19",
    "@storybook/addon-interactions": "^6.4.19",
    "@storybook/addon-links": "^6.4.19",
    "@storybook/builder-webpack5": "^6.4.19",
    "@storybook/manager-webpack5": "^6.4.19",
    "@storybook/node-logger": "^6.4.19",
    "@storybook/preset-create-react-app": "^4.0.1",
    "@storybook/react": "^6.4.19",
    "@storybook/testing-library": "^0.0.9",
    "@testing-library/jest-dom": "^5.16.2",
    "@testing-library/react": "^12.1.4",
    "@testing-library/react-hooks": "^7.0.2",
    "@types/jest": "^27.4.1",
    "@types/styled-components": "^5.1.20",
    "jest": "^27.5.1",
    "react-test-renderer": "^17.0.2",
    "ts-jest": "^27.1.3",
    "webpack": "^5.70.0"
  }
}

I can give out a lot of info about this project, so if more info is required just ask! :D

2
  • Can you please try after removing "extends": [ "react-app", "react-app/jest" ], from eslintConfig section in package.json Commented Apr 13, 2022 at 13:52
  • @SachinVairagi still getting the same error :( Btw I am using docker-compose up --build Commented Apr 14, 2022 at 5:52

2 Answers 2

4

I figured it out. I asked a friend, and he helped me out. I needed to change my Dockerfile to:

FROM node:16.14.2

WORKDIR /usr/src/app

RUN npm install -g react-scripts

RUN chown -Rh node:node /usr/src/app

USER node

EXPOSE 3000

CMD [ "sh", "-c", "npm install && npm run start" ]
Sign up to request clarification or add additional context in comments.

3 Comments

Does it work nice with docker "one process per container" policy?
To answer my own question: No. It does not play nice, and this trick will cost us extra seconds docker will need to stop container.
Update: replacing just npm run start with direct invokation to react-scripts, and adding init: true option to docker compose allows Docker to manage container with SIGNALs. So no slow container reload.
-1

Your Dockerfile is missing the application code; it only copies the package.json file in. This gives you an incomplete image that you can't just run. You're missing a line:

COPY ./ ./

I'd put this after the RUN npm install line, to make rebuilding the image faster.

Since your image is incomplete, in your current setup you have to inject the code from the host, and that hides the node_modules directory that the image builds. That's why you also have to run npm install on the host. If you COPY the application code into the image, you don't need the volumes: block.

version: '3.8'
services:
    frontend:
        build: ./apps/frontend  # short form with default dockerfile:
        ports:
            - 3000:3000
        environment:
            - API_BASE_URL=host.docker.internal:8080/api
        extra_hosts:
            - "host.docker.internal:host-gateway"
        # no volumes: or polling environment variable

2 Comments

For local dev, code changes will not propagate with this solution.
For local dev, I wouldn't expect you to try to work inside an isolated Docker container. Write your code using a host IDE, run its unit tests using a host Node interpreter, and then bring Docker in only when you require its isolation features. If the code isn't built into the image or if you always ovewrite it with a volume mount, you're only using Docker as an inconvenient way to get a Node interpreter, and there are easier ways to do that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.