feat: add Docker deployment for crypto-commons.org

- Add Dockerfile with nginx for static site serving
- Add docker-compose.yml with Traefik labels
- Update Next.js to 16.0.7 (security fix)
- Remove deprecated eslint config from next.config.mjs

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2025-12-06 16:23:54 +01:00
parent 540f6599d3
commit 4073880af5
6 changed files with 3995 additions and 5 deletions

8
.dockerignore Normal file
View File

@ -0,0 +1,8 @@
Dockerfile
.dockerignore
node_modules
.next
out
.git
.gitignore
README.md

44
Dockerfile Normal file
View File

@ -0,0 +1,44 @@
FROM node:20-alpine AS builder
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci --legacy-peer-deps
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
# Production image with nginx
FROM nginx:alpine AS runner
# Copy static export to nginx
COPY --from=builder /app/out /usr/share/nginx/html
# Custom nginx config for SPA routing
RUN echo 'server { \
listen 80; \
server_name _; \
root /usr/share/nginx/html; \
index index.html; \
\
location / { \
try_files $uri $uri.html $uri/ /index.html; \
} \
\
# Cache static assets \
location /_next/static/ { \
expires 1y; \
add_header Cache-Control "public, immutable"; \
} \
\
# Security headers \
add_header X-Frame-Options "SAMEORIGIN" always; \
add_header X-Content-Type-Options "nosniff" always; \
}' > /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

16
docker-compose.yml Normal file
View File

@ -0,0 +1,16 @@
services:
cca-website:
build: .
container_name: cca-website
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.cca.rule=Host(`crypto-commons.org`) || Host(`www.crypto-commons.org`)"
- "traefik.http.routers.cca.entrypoints=web,websecure"
- "traefik.http.services.cca.loadbalancer.server.port=80"
networks:
- traefik-public
networks:
traefik-public:
external: true

View File

@ -1,9 +1,6 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
output: 'export', output: 'export',
eslint: {
ignoreDuringBuilds: true,
},
typescript: { typescript: {
ignoreBuildErrors: true, ignoreBuildErrors: true,
}, },

3925
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -46,7 +46,7 @@
"embla-carousel-react": "8.5.1", "embla-carousel-react": "8.5.1",
"input-otp": "1.4.1", "input-otp": "1.4.1",
"lucide-react": "^0.454.0", "lucide-react": "^0.454.0",
"next": "16.0.0", "next": "^16.0.7",
"next-themes": "latest", "next-themes": "latest",
"react": "19.2.0", "react": "19.2.0",
"react-day-picker": "9.8.0", "react-day-picker": "9.8.0",
@ -70,4 +70,4 @@
"tw-animate-css": "1.3.3", "tw-animate-css": "1.3.3",
"typescript": "^5" "typescript": "^5"
} }
} }