server { listen 80; # Required explicitly: the nginx image's 10-listen-on-ipv6-by-default.sh # only patches the stock default.conf. We replace that file, so without # this line the container listens on IPv4 only while HEALTHCHECK wget # resolves localhost to ::1 and fails → Docker reports unhealthy. listen [::]:80; server_name _; root /usr/share/nginx/html; index index.html; # Hashed Vite chunks must 404 as application/octet-stream/empty — never # fall through to index.html (that yields MIME "text/html" and breaks # dynamic import() in the browser). location /assets/ { try_files $uri =404; expires 1y; add_header Cache-Control "public, immutable"; access_log off; } location = /index.html { add_header Cache-Control "no-cache, no-store, must-revalidate"; } # Vue Router history mode — unmatched paths fall through to the SPA shell. location / { try_files $uri $uri/ /index.html; } gzip on; gzip_types text/css application/javascript application/json image/svg+xml; gzip_min_length 1024; }