From b1bc3bd38b665067d1eb57b9a6cde36409abc57a Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sat, 22 Nov 2025 17:49:56 -0800 Subject: [PATCH] Add Docker deployment configuration for dokindthings.fund MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Dockerfile with multi-stage build for optimized production image - Add docker-compose.yml for easy container management - Add Nginx reverse proxy configuration with SSL support - Update next.config.mjs to enable standalone output mode - Add .dockerignore to optimize build process - Add DEPLOYMENT.md with comprehensive deployment instructions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .dockerignore | 9 +++ DEPLOYMENT.md | 119 +++++++++++++++++++++++++++++++++++ Dockerfile | 50 +++++++++++++++ docker-compose.yml | 17 +++++ next.config.mjs | 3 +- nginx/dokindthings.fund.conf | 46 ++++++++++++++ 6 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 DEPLOYMENT.md create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 nginx/dokindthings.fund.conf diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..7a58ea7 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +Dockerfile +.dockerignore +node_modules +npm-debug.log +.next +.git +.gitignore +README.md +nginx diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..7f7fb7a --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,119 @@ +# Deployment Instructions for dokindthings.fund + +This guide will help you deploy the Kindness Fund website to your private server at dokindthings.fund. + +## Prerequisites + +- Docker and Docker Compose installed on your server +- Nginx installed and configured +- Domain `dokindthings.fund` pointing to your server's IP address +- SSL certificate (Let's Encrypt recommended) + +## Step 1: Clone the Repository + +On your server, clone the repository from your Gitea instance: + +```bash +git clone https://gitea.jeffemmett.com/jeffemmett/kindness-fund-website.git +cd kindness-fund-website +``` + +## Step 2: Build and Start the Docker Container + +```bash +# Create the external network if it doesn't exist +docker network create web + +# Build and start the container +docker compose up -d --build +``` + +The application will be available on port 3001 locally. + +## Step 3: Configure Nginx + +Copy the Nginx configuration to your Nginx sites-available directory: + +```bash +sudo cp nginx/dokindthings.fund.conf /etc/nginx/sites-available/dokindthings.fund +sudo ln -s /etc/nginx/sites-available/dokindthings.fund /etc/nginx/sites-enabled/ +``` + +## Step 4: Set Up SSL Certificate + +If you don't have an SSL certificate yet, use Let's Encrypt: + +```bash +sudo certbot --nginx -d dokindthings.fund -d www.dokindthings.fund +``` + +This will automatically obtain and configure the SSL certificate. + +If you already have certificates, update the paths in the Nginx configuration file. + +## Step 5: Test and Reload Nginx + +Test the Nginx configuration: + +```bash +sudo nginx -t +``` + +If the test passes, reload Nginx: + +```bash +sudo systemctl reload nginx +``` + +## Step 6: Verify Deployment + +Visit https://dokindthings.fund in your browser to verify the site is working. + +## Updating the Site + +To update the site with new changes: + +```bash +cd kindness-fund-website +git pull +docker compose down +docker compose up -d --build +``` + +## Troubleshooting + +### Check Docker Container Logs + +```bash +docker logs kindness-fund-website +``` + +### Check Nginx Logs + +```bash +sudo tail -f /var/log/nginx/dokindthings.fund.error.log +sudo tail -f /var/log/nginx/dokindthings.fund.access.log +``` + +### Check Container Status + +```bash +docker ps +``` + +### Rebuild Container + +If you need to completely rebuild: + +```bash +docker compose down +docker compose build --no-cache +docker compose up -d +``` + +## Notes + +- The application runs on port 3001 internally +- Nginx acts as a reverse proxy, forwarding HTTPS traffic from port 443 to port 3001 +- The Docker container will automatically restart unless stopped manually +- Make sure your firewall allows traffic on ports 80 and 443 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4c6fb2d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,50 @@ +FROM node:20-alpine AS base + +# Install dependencies only when needed +FROM base AS deps +RUN apk add --no-cache libc6-compat +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json pnpm-lock.yaml* ./ +RUN corepack enable pnpm && pnpm i --frozen-lockfile + +# Rebuild the source code only when needed +FROM base AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . + +# Disable telemetry during build +ENV NEXT_TELEMETRY_DISABLED=1 + +RUN corepack enable pnpm && pnpm run build + +# Production image, copy all the files and run next +FROM base AS runner +WORKDIR /app + +ENV NODE_ENV=production +ENV NEXT_TELEMETRY_DISABLED=1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public + +# Set the correct permission for prerender cache +RUN mkdir .next +RUN chown nextjs:nodejs .next + +# Automatically leverage output traces to reduce image size +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 3000 + +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +CMD ["node", "server.js"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b0b635c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +services: + kindness-fund-website: + build: + context: . + dockerfile: Dockerfile + container_name: kindness-fund-website + restart: unless-stopped + ports: + - "3001:3000" + environment: + - NODE_ENV=production + networks: + - web + +networks: + web: + external: true diff --git a/next.config.mjs b/next.config.mjs index 5501ef9..10ddff2 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,12 +1,13 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + output: 'standalone', typescript: { ignoreBuildErrors: true, }, images: { unoptimized: true, }, - + } export default nextConfig \ No newline at end of file diff --git a/nginx/dokindthings.fund.conf b/nginx/dokindthings.fund.conf new file mode 100644 index 0000000..da9ac35 --- /dev/null +++ b/nginx/dokindthings.fund.conf @@ -0,0 +1,46 @@ +server { + listen 80; + listen [::]:80; + server_name dokindthings.fund www.dokindthings.fund; + + # Redirect HTTP to HTTPS + return 301 https://$server_name$request_uri; +} + +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + server_name dokindthings.fund www.dokindthings.fund; + + # SSL Certificate paths (update these with your actual certificate paths) + ssl_certificate /etc/letsencrypt/live/dokindthings.fund/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/dokindthings.fund/privkey.pem; + + # SSL configuration + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + + # Logging + access_log /var/log/nginx/dokindthings.fund.access.log; + error_log /var/log/nginx/dokindthings.fund.error.log; + + # Proxy settings + location / { + proxy_pass http://localhost:3001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "no-referrer-when-downgrade" always; +}