From 03d4adf6b1aa65c1823e3c65d55042aca09a5949 Mon Sep 17 00:00:00 2001 From: Grzegorz Kucmierz Date: Sun, 15 Feb 2026 20:36:02 +0100 Subject: [PATCH] Align configuration with nonograms: add healthcheck, nginx security, build from source --- Dockerfile | 26 +++++++++++++++++++++----- docker-compose.yml | 6 ++++-- nginx.conf | 41 +++++++++++++++++++++++++++++++++++------ 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6e1e6a0..2847754 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,36 @@ -# Build stage -FROM node:18-alpine AS builder +# Stage 1: Build the application +FROM node:18-alpine as build-stage +# Set working directory WORKDIR /app +# Copy package files first to leverage Docker cache COPY package*.json ./ + +# Install dependencies RUN npm install +# Copy the rest of the application code COPY . . + +# Build the application RUN npm run build -# Production stage -FROM nginx:stable-alpine +# Stage 2: Serve the application with Nginx +FROM nginx:stable-alpine as production-stage -COPY --from=builder /app/dist /usr/share/nginx/html +# Copy the built artifacts from the build stage +COPY --from=build-stage /app/dist /usr/share/nginx/html + +# Copy custom Nginx configuration COPY nginx.conf /etc/nginx/conf.d/default.conf +# Expose port 80 EXPOSE 80 +# Healthcheck to ensure Nginx is running and serving +HEALTHCHECK --interval=30s --timeout=3s \ + CMD wget --quiet --tries=1 --spider http://localhost/health || exit 1 + +# Start Nginx CMD ["nginx", "-g", "daemon off;"] diff --git a/docker-compose.yml b/docker-compose.yml index 61e3fe0..d67a48d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,11 +2,13 @@ version: '3.8' services: rubic-cube: - image: gitea.7u.pl/gkucmierz/rubic-cube:latest container_name: rubic-cube - restart: always + build: + context: . + dockerfile: Dockerfile ports: - "8083:80" + restart: always networks: - rubic-net diff --git a/nginx.conf b/nginx.conf index 40b9650..45be951 100644 --- a/nginx.conf +++ b/nginx.conf @@ -1,15 +1,44 @@ server { - listen 80; - server_name localhost; + listen 80; + server_name localhost; + root /usr/share/nginx/html; + index index.html; + + # Gzip compression + gzip on; + gzip_vary on; + gzip_min_length 10240; + gzip_proxied expired no-cache no-store private auth; + gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml application/javascript; + gzip_disable "MSIE [1-6]\."; + + # Security Headers + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Content-Type-Options "nosniff"; + add_header Referrer-Policy "strict-origin-when-cross-origin"; + # CSP: Adjust as needed. This is a strict starting point. + # Allowing unsafe-inline for styles is often necessary for Vue apps unless using nonces. + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:;"; location / { - root /usr/share/nginx/html; - index index.html index.htm; try_files $uri $uri/ /index.html; } - error_page 500 502 503 504 /50x.html; + # Cache static assets + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ { + expires 1y; + add_header Cache-Control "public, no-transform"; + } + + # Health check + location /health { + access_log off; + return 200 "healthy\n"; + } + + error_page 500 502 503 504 /50x.html; location = /50x.html { - root /usr/share/nginx/html; + root /usr/share/nginx/html; } }