reactjsdockerdocker-composetailwind-csscraco

Docker fails to build - Create React App + Tailwind /bin/sh: craco: not found


I've been stuck with this problem for a couple of days now. I am trying to dockerize a django REST API + react (create-react-app) application. The react application uses craco for building since I am using tailwindcss. I followed the this guide to integrate Tailwind with the React app and it's working when I run yarn start locally.

Guide: https://tailwindcss.com/docs/guides/create-react-app

The problem is it is throwing /bin/sh: craco: not found error when I run it using docker-compose. I even tried adding RUN yarn add @craco/craco -g after RUN yarn in the frontend Dockerfile but it is showing the same error.

Error when running docker-compose up --build:

...
Step 8/9 : COPY . /app/frontend/
 ---> 19e0247cde64
Step 9/9 : EXPOSE 3000
 ---> Running in 43f7d970d460
Removing intermediate container 43f7d970d460
 ---> a20ae2148d4b

Successfully built a20ae2148d4b
Successfully tagged react_frontend:latest
Creating react_frontend_container ... done
Attaching to react_frontend_container
yarn run v1.22.15
$ craco start
frontend_1  | /bin/sh: craco: not found
error Command failed with exit code 127.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
react_frontend_container exited with code 127

Frontend Dockerfile:

FROM node:16-alpine

WORKDIR /app/frontend

COPY package.json .
COPY yarn.lock .

RUN yarn

COPY . /app/frontend/
EXPOSE 3000

docker-compose.yml:

version: '3.8'

services:
  ... (postgres db and django api services)

  frontend:
    build: ./frontend
    command: ["yarn", "start"]
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    volumes:
      - ./frontend:/app/frontend
      - node-modules:/app/frontend/node_modules
    container_name: react_frontend_container
    ports:
      - "3000:3000"

volumes:
  node-modules:

package.json:

{
  "name": "frontend",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@craco/craco": "^6.4.3",
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.0.1"
  },
  "scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "autoprefixer": "^9",
    "postcss": "^7",
    "tailwindcss": "npm:@tailwindcss/postcss7-compat"
  }
}

Solution

  • The issue is that you map your host directory and volume onto the directories in the image that contain the node modules and the app files.

    Try removing this section in the docker-compose file. That way you won't overwrite what's in the image and craco will be available.

    volumes:
      - ./frontend:/app/frontend
      - node-modules:/app/frontend/node_modules
    

    One thing to be aware of when you use docker-compose to both build and run your image, is that the volumes are only mapped during the run phase and not during the build.