Home > Blockchain >  Dockerized React build renders empty page
Dockerized React build renders empty page

Time:12-27

I have a React project initialized with create-react-app, that I am building and deploying inside of a Docker container. When the container is ran, the build finishes without any error, the folder with build is created inside of it and I can deploy and get to the index.html. The problem being, that index.html does not seem to call for any of the built JavaScript. This on the other hand is not the case on host machine, where the build works without any problem. There are no environment variables that I am aware off (I did not manually add any), that should be on host system, affecting this.

I will ignore React code as it works on host and build did not throw any error.

This is my docker-compose.yml:

# docker compose -f docker-compose.yml --env-file ./env/prod.env up -d --build
version: "3.9"
services:
  admin-console:
    env_file: ./env/prod.env
    image: "eaap-admin-console"
    volumes:
      - ./modules/admin-console:/usr/src/app:delegated
      - /usr/src/app/node_modules
    build: 
      context: ./modules/admin-console
      target: ${BUILD_TARGET}
      args:
        - ADMIN_CONSOLE_CONTAINER_PORT=${ADMIN_CONSOLE_CONTAINER_PORT}

This is the prod.env:

# =====================================
# GLOBAL
# =====================================
BUILD_TARGET=prod
# =====================================
# admin-console
# =====================================
# ----------------------------------------
# General:
# ---
ADMIN_CONSOLE_BASE_URL=http://host.docker.internal:3012
# ----------------------------------------
# Environment:
# ---

# ----------------------------------------
# Ports:
# ---

# Port on which app runs on host machine
ADMIN_CONSOLE_CONTAINER_PORT=8080
# Port on which app runs on inside container
ADMIN_CONSOLE_HOST_PORT=3012

This is my Dockerfile:

# =====================================
#               BASE
# =====================================
ARG ADMIN_CONSOLE_CONTAINER_PORT=80
FROM node:16-alpine3.15 as base
# Create app directory
WORKDIR /usr/src/app
# =====================================
#               INSTALL
# =====================================
FROM base as install
COPY ./package*.json ./
RUN npm install
COPY . .
# =====================================
#               DEVINSTALL
# =====================================
# Dev install is using a volume to copy source
FROM install as devInstall
RUN npm install
# =====================================
#               TEST
# =====================================
FROM install as test
RUN CI=true npm run test 
# =====================================
#               PROD
# =====================================
FROM install as prod
RUN npm run build
CMD ["npx", "http-server"]

And this is package.json:

{
  "name": "react-boilerplate",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@emotion/react": "^11.10.4",
    "@emotion/styled": "^11.10.4",
    "@mui/material": "^5.10.5",
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/user-event": "^13.5.0",
    "@types/jest": "^27.5.2",
    "@types/node": "^16.11.45",
    "@types/react": "^18.0.15",
    "@types/react-dom": "^18.0.6",
    "eslint-config-prettier": "^8.5.0",
    "install": "^0.13.0",
    "npm": "^8.19.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-flow-renderer": "^10.3.16",
    "react-router": "^6.3.0",
    "react-router-dom": "^6.3.0",
    "react-scripts": "5.0.1",
    "socket.io-client": "^4.5.2",
    "styled-components": "^5.3.6",
    "web-vitals": "^2.1.4",
    "zustand": "^4.1.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject",
    "lint": "eslint src --fix"
  },
  "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": {
    "@testing-library/react": "^13.3.0",
    "@types/styled-components": "^5.1.26",
    "@typescript-eslint/eslint-plugin": "^5.42.1",
    "eslint": "^8.2.0",
    "eslint-config-airbnb": "^19.0.4",
    "eslint-config-standard-with-typescript": "^23.0.0",
    "eslint-plugin-import": "^2.25.3",
    "eslint-plugin-jsx-a11y": "^6.5.1",
    "eslint-plugin-n": "^15.5.1",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-promise": "^6.1.1",
    "eslint-plugin-react": "^7.28.0",
    "eslint-plugin-react-hooks": "^4.3.0",
    "http-server": "^14.1.1",
    "typescript": "^4.8.4"
  }
}

I am connecting to it from host machines browser on URL: http://localhost:3012

There is one anomaly I have noticed, which is that <link> to the manifest.json is:

<link rel="manifest" href="%PUBLIC_URL%/manifest.json">

Which of course point's nowhere, whereas when built is ran and deployed on host which same method, it is:

<link href="/static/css/main.8cd4d5c3.css" rel="stylesheet">

This is the case for every tag importing data. I did try to add homepage to package.json, PUBLIC_URL environment variable into build-args and container itself, but this did not make any difference.

I have also tried to delete both the image and container and remove volumes, also without any results.

Any help or guidance would be appreciated.

CodePudding user response:

I will leave it here, as it's a mistake someone else can easily make. I forgot to switch the folder to ./build when starting the server and npx http-server defaulted to running ./public folder instead of ./build

The solution in this case is to add WORKDIR pointing to the build folder:

FROM install as prod
RUN npm run build
WORKDIR /usr/src/app/build
CMD ["npx", "http-server"]
  • Related