Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ jobs:
uses: actions/checkout@v4

- name: Build Docker image
run: docker build -t react-portfolio .
run: docker build -t react-nginx-prod .
19 changes: 13 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
FROM node:20.19.0
# ---------- Stage 1: Build ----------
FROM node:20.19.0 AS builder

WORKDIR /app

COPY package*.json ./
RUN npm install
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The builder stage should explicitly use npm ci instead of npm install for more deterministic and faster builds in production environments. The npm ci command installs dependencies based on package-lock.json exactly, removes node_modules if it exists, and is optimized for CI/CD pipelines.

Suggested change
RUN npm install
RUN npm ci

Copilot uses AI. Check for mistakes.

COPY . .

# This will fail the Docker build if there are TypeScript/build errors
RUN npm run build

# Verify that the build directory exists
RUN test -d dist || (echo "Build failed - dist directory not found" && exit 1)
# ---------- Stage 2: Production ----------
FROM nginx:alpine
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nginx:alpine image runs as root by default, which is a security risk. Consider running the nginx process as a non-root user for better security. This can be achieved by creating a non-root user and adjusting file permissions, or by using an image that runs nginx as non-root by default.

Copilot uses AI. Check for mistakes.

# Remove default nginx static files
RUN rm -rf /usr/share/nginx/html/*

# Copy build output from builder stage
COPY --from=builder /app/dist /usr/share/nginx/html

Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nginx configuration is missing a custom config file to handle client-side routing for the React SPA. Since this application uses react-router-dom with BrowserRouter, direct navigation to routes (e.g., /about) or page refreshes will result in 404 errors from nginx. You need to add a custom nginx configuration that serves index.html for all routes to ensure the React router handles the routing. This should include a try_files directive that falls back to index.html for all requests that don't match static files.

Suggested change
# Configure nginx for React SPA routing
RUN printf 'server {\n\
listen 80;\n\
server_name _;\n\
root /usr/share/nginx/html;\n\
index index.html;\n\
\n\
location / {\n\
try_files $$uri $$uri/ /index.html;\n\
}\n\
}\n' > /etc/nginx/conf.d/default.conf

Copilot uses AI. Check for mistakes.
EXPOSE 80

CMD ["sh", "-c", "echo Build completed successfully"]
CMD ["nginx", "-g", "daemon off;"]