Docker and React

Hello,
I’m asking for help from those who have set up React with Docker. Is my compose file and Dockerfile wrong?

...
portal:
    container_name: portal
    build:
      context: /home/dev/
      dockerfile: Dockerfile
    environment:
      - NODE_ENV=development
      - CHOKIDAR_USEPOLLING="true"
      - USER_ID=${USER_ID:-999}
      - GROUP_ID=${GROUP_ID:-995}
    user: "${USER_ID:-999}:${GROUP_ID:-995}"
    volumes:
      - /home/dev/:/app
      - /app/node_modules          
      - /app/.next
    ports:
      - "127.0.0.1:3000:3000"               
    deploy:
      resources:
        limits:
          cpus: '4.0'
          memory: 4G

And:

FROM node:23-alpine

# Create non-root user with configurable UID/GID
ARG USER_ID=999
ARG GROUP_ID=995

RUN addgroup -g ${GROUP_ID} appuser && \
    adduser -S -u ${USER_ID} -G appuser appuser

WORKDIR /app

COPY package*.json ./

# Install dependencies as root first
RUN npm install -g npm@latest && \
    npm install --legacy-peer-deps

# Create .next directory with correct permissions
RUN mkdir -p /app/.next && \
    chown -R ${USER_ID}:${GROUP_ID} /app/.next

COPY --chown=${USER_ID}:${GROUP_ID} . .

# Ensure proper permissions for node_modules
RUN chown -R ${USER_ID}:${GROUP_ID} /app/node_modules

USER ${USER_ID}

EXPOSE 3000

CMD ["npm", "run", "dev"]

Sometimes the following error appears:

What is wrong?

Thank you.

Your docker-compose.yml and Dockerfile setup for a React application looks mostly correct, but there are a few potential issues and improvements that might help resolve errors and improve the setup.

Improved docker-compose.yml

portal:
  container_name: portal
  build:
    context: /home/dev/
    dockerfile: Dockerfile
  environment:
    - NODE_ENV=development
    - CHOKIDAR_USEPOLLING=true
    - USER_ID=${USER_ID:-999}
    - GROUP_ID=${GROUP_ID:-995}
  volumes:
    - /home/dev/:/app
    - /app/.next
  ports:
    - "127.0.0.1:3000:3000"
  deploy:
    resources:
      limits:
        cpus: '4.0'
        memory: 4G

Improved Dockerfile

FROM node:23-alpine

# Create non-root user with configurable UID/GID
ARG USER_ID=999
ARG GROUP_ID=995

RUN addgroup -g ${GROUP_ID} appuser && \
    adduser -S -u ${USER_ID} -G appuser appuser

WORKDIR /app

COPY package*.json ./

# Install dependencies as root first
RUN npm install -g npm@latest && \
    npm install --legacy-peer-deps

# Create .next directory with correct permissions
RUN mkdir -p /app/.next && \
    chown -R ${USER_ID}:${GROUP_ID} /app/.next

COPY --chown=${USER_ID}:${GROUP_ID} . .

# Ensure proper permissions for node_modules
RUN chown -R ${USER_ID}:${GROUP_ID} /app/node_modules

USER ${USER_ID}

EXPOSE 3000

CMD ["npm", "run", "dev"]

Hello,
Thank you so much for your reply.
You have removed the line /app/node_modules and this causes node_modules directory to be created on the host with root permissions which is causing the problem.

so this means the issue has been resolved.

Hello,
Not really. I got:

✓ Starting...
Error: EISDIR: illegal operation on a directory, open '/app/next-env.d.ts'
    at async open (node:internal/fs/promises:634:25)
    at async Object.writeFile (node:internal/fs/promises:1208:14)
    at async writeAppTypeDeclarations (/app/node_modules/next/dist/lib/typescript/writeAppTypeDeclarations.js:59:5)
    at async verifyTypeScriptSetup (/app/node_modules/next/dist/lib/verify-typescript-setup.js:124:9)
    at async verifyTypeScript (/app/node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.js:112:26)
    at async startWatcher (/app/node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.js:139:29)
    at async setupDevBundler (/app/node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.js:775:20)
    at async Span.traceAsyncFn (/app/node_modules/next/dist/trace/trace.js:154:20)
    at async initialize (/app/node_modules/next/dist/server/lib/router-server.js:80:30)
    at async Server.<anonymous> (/app/node_modules/next/dist/server/lib/start-server.js:249:36) {
  errno: -21,
  code: 'EISDIR',
  syscall: 'open',
  path: '/app/next-env.d.ts'
}

I have come to the conclusion that Docker does not have a clear rule.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.