Search code examples
dockercreate-react-app

SASS_PATH not recognized when running "yarn build" in Dockerized create-react-app


I'm currently developing a CRA app using Docker. Everything is fine in development. However, when I want to create the production build (I'm using a separate docker-compose.yml file for the production build), it keeps telling me it cannot find the files.

I keep getting Cannot find module: 'lorem.scss'. Make sure this package is installed. It happens right after yarn run build in the building environment.

My Dockerfile:

##############################
# Base Image
##############################
# Ger current Node Alpine Linux image.
FROM node:alpine AS base
# Set working directory.
WORKDIR /home/node/app/
# Copy project content.
COPY package.json ./

##############################
# Development Image
##############################
# Development environment.
FROM base AS development
# Run yarn to install.
RUN yarn
# Copy source code.
COPY ./src/ /home/node/app/src/
COPY ./public/ /home/node/app/public/
# Copy Storybook files.
COPY ./stories/ /home/node/app/stories/
COPY ./.storybook/ /home/node/app/.storybook/
# Run the app.
CMD [ "yarn", "run", "dev" ]

##############################
# Building Environment
##############################
# Building environment set.
FROM base AS builder
# Run yarn to install.
RUN yarn
# Copy source code.
COPY ./src/ /home/node/app/src/
COPY ./public/ /home/node/app/public/
# Run the build.
RUN yarn run build

##############################
# Production Image
##############################
FROM nginx:alpine AS production
# Copy source code.
COPY --from=builder /home/node/app/build /usr/share/nginx/html
# Copy nginx configuration template.
COPY ./nginx.template /etc/nginx/conf.d/
# Set permissions so nginx can serve it.
RUN chown nginx.nginx /usr/share/nginx/html/ -R

My docker-compose.production.yml file:

version: "3.7"
services:
##############################
# Front-End Container
##############################
  frontend:
    container_name: ${PROJECT_NAME}_frontend
    build:
      context: ./frontend/
      target: production
    restart: always
    environment:
      - PROJECT_NAME=${PROJECT_NAME}
      - NODE_PATH=${REACT_NODE_PATH}
      - NODE_PORT=${NODE_PORT}
      - SASS_PATH=${SASS_PATH}
      - NODE_ENV=production
      - DOCKER_BUILDKIT=1
    command: /bin/ash -c "envsubst < /etc/nginx/conf.d/nginx.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"
    expose:
      - "80"
    ports:
      - "80:80"

My variables in the .env file are as follows:

SASS_PATH=node_modules:src/components:src/assets/styles:src/assets/fonts
REACT_NODE_PATH=src/assets/styles/pages:src/assets/images

Solution

  • Your problem is that you are expecting the environment files to be passed to your docker build. While there is nothing like that happening. The environment that you define is only passed to image at run-time as run-time environment.

    So you need to either use build arguments or set these environments in your image

    Passing environments

    ##############################
    # Building Environment
    ##############################
    # Building environment set.
    FROM base AS builder
    # Run yarn to install.
    RUN yarn
    # Copy source code.
    COPY ./src/ /home/node/app/src/
    COPY ./public/ /home/node/app/public/
    # Run the build.
    ENV SASS_PATH=node_modules:src/components:src/assets/styles:src/assets/fonts REACT_NODE_PATH=src/assets/styles/pages:src/assets/images
    RUN yarn run build
    

    Or you need to use build args

    ##############################
    # Building Environment
    ##############################
    # Building environment set.
    FROM base AS builder
    # Run yarn to install.
    RUN yarn
    # Copy source code.
    COPY ./src/ /home/node/app/src/
    COPY ./public/ /home/node/app/public/
    # Run the build.
    ARG SASS_PATH
    ARG REACT_NODE_PATH
    ENV SASS_PATH=${SASS_PATH}
    ENV REACT_NODE_PATH=${REACT_NODE_PATH}
    RUN yarn run build
    

    And update your compose file like

    version: "3.7"
    services:
    ##############################
    # Front-End Container
    ##############################
      frontend:
        container_name: ${PROJECT_NAME}_frontend
        build:
          context: ./frontend/
          target: production
          args:
            - REACT_NODE_PATH=${REACT_NODE_PATH}
            - SASS_PATH=${SASS_PATH}
        restart: always
        environment:
          - PROJECT_NAME=${PROJECT_NAME}
          - NODE_PATH=${REACT_NODE_PATH}
          - NODE_PORT=${NODE_PORT}
          - SASS_PATH=${SASS_PATH}
          - NODE_ENV=production
          - DOCKER_BUILDKIT=1
        command: /bin/ash -c "envsubst < /etc/nginx/conf.d/nginx.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"
        expose:
          - "80"
        ports:
          - "80:80"