# Dockerfile for Astro webapp with NGINX and API for content management # Stage 1: Build the Astro application FROM node:20-alpine as build WORKDIR /app # Copy package files. If src/api has its own package.json, handle it here or in a dedicated API build stage. COPY package.json package-lock.json* ./ # Ensure src/api/package.json is copied if it exists and is used for API dependencies # COPY src/api/package.json src/api/package-lock.json* ./src/api/ RUN npm ci # Copy the rest of the application code # Ensure .dockerignore is properly set up to exclude node_modules etc. from host COPY . . # Build the Astro project (generates into /app/dist) RUN npm run build # If API has separate build step, include it here. # Example: RUN npm run build --workspace=api (if using npm workspaces) # Stage 2: Serve with NGINX and Node API FROM nginx:alpine # Create a non-root user and group RUN addgroup -S appgroup && adduser -S -G appgroup appuser # Install Node.js for the API server and su-exec for user switching RUN apk add --no-cache nodejs npm su-exec # Set base working directory WORKDIR /app # Copy built static files from build stage to NGINX html directory COPY --from=build /app/dist /usr/share/nginx/html RUN chown -R appuser:appgroup /usr/share/nginx/html && chmod -R 755 /usr/share/nginx/html # Copy API files from build stage # Ensure that node_modules for the API are correctly copied or installed here. COPY --from=build /app/src/api /app/api # If API node_modules were part of the build stage under /app/api/node_modules, copy them: # COPY --from=build --chown=appuser:appgroup /app/api/node_modules /app/api/node_modules # Or, if API has its own package.json and it was copied to /app/api in build stage: COPY --from=build /app/api/package.json /app/api/package-lock.json* /app/api/ WORKDIR /app/api RUN npm ci --omit=dev --ignore-scripts # Install production API dependencies RUN chown -R appuser:appgroup /app/api # Copy custom NGINX configuration # This replaces the RUN echo '...' command COPY nginx.conf /etc/nginx/conf.d/default.conf RUN chown appuser:appgroup /etc/nginx/conf.d/default.conf && chmod 644 /etc/nginx/conf.d/default.conf # Ensure Nginx can write to its log directory (usually /var/log/nginx) # Alpine Nginx base image usually sets this up correctly. If not, create and chown /var/log/nginx. RUN mkdir -p /var/log/nginx && chown -R appuser:appgroup /var/log/nginx RUN mkdir -p /run/nginx && chown -R appuser:appgroup /run/nginx # For PID file # Copy start script from build stage COPY --from=build /app/start.sh /app/start.sh RUN chmod +x /app/start.sh && chown appuser:appgroup /app/start.sh # Create and set permissions for content directory RUN mkdir -p /app/content/books && chown -R appuser:appgroup /app/content # Expose port 80 (Nginx will listen on this port) EXPOSE 80 # Switch to non-root user for running the application USER appuser # Start NGINX and API server using the start script # The start.sh script will use su-exec for the Node API part if needed, # but since we USER appuser, nginx and node will run as appuser. CMD ["/app/start.sh"]