Files
sexy.pivoine.art/DOCKER.md
Valknar XXX bcc9ba1c6d feat: docker
2025-10-25 22:29:06 +02:00

8.2 KiB

Docker Deployment Guide

This guide covers building and deploying sexy.pivoine.art using Docker.

Overview

The Dockerfile uses a multi-stage build process:

  1. Base stage: Sets up Node.js and pnpm
  2. Builder stage: Installs Rust, compiles WASM, builds all packages
  3. Runner stage: Minimal production image with only runtime dependencies

Prerequisites

  • Docker 20.10+ with BuildKit support
  • Docker Compose 2.0+ (optional, for orchestration)

Building the Image

Basic Build

docker build -t sexy.pivoine.art:latest .

Build with Build Arguments

docker build \
  --build-arg NODE_ENV=production \
  -t sexy.pivoine.art:latest \
  .

Multi-platform Build (for ARM64 and AMD64)

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t sexy.pivoine.art:latest \
  --push \
  .

Running the Container

Run with Environment Variables

docker run -d \
  --name sexy-pivoine-frontend \
  -p 3000:3000 \
  -e PUBLIC_API_URL=https://api.pivoine.art \
  -e PUBLIC_URL=https://sexy.pivoine.art \
  -e PUBLIC_UMAMI_ID=your-umami-id \
  -e LETTERSPACE_API_URL=https://api.letterspace.com/v1 \
  -e LETTERSPACE_API_KEY=your-api-key \
  -e LETTERSPACE_LIST_ID=your-list-id \
  sexy.pivoine.art:latest

Run with Environment File

# Create .env.production from template
cp .env.production.example .env.production

# Edit .env.production with your values
nano .env.production

# Run container
docker run -d \
  --name sexy-pivoine-frontend \
  -p 3000:3000 \
  --env-file .env.production \
  sexy.pivoine.art:latest

Docker Compose Deployment

Using docker-compose.production.yml

# 1. Create environment file
cp .env.production.example .env.production

# 2. Edit environment variables
nano .env.production

# 3. Build and start
docker-compose -f docker-compose.production.yml up -d --build

# 4. View logs
docker-compose -f docker-compose.production.yml logs -f frontend

# 5. Stop services
docker-compose -f docker-compose.production.yml down

Scale the Application

docker-compose -f docker-compose.production.yml up -d --scale frontend=3

Environment Variables Reference

Required Variables

Variable Description Example
PUBLIC_API_URL Directus API backend URL https://api.pivoine.art
PUBLIC_URL Frontend application URL https://sexy.pivoine.art

Optional Variables

Variable Description Example
PUBLIC_UMAMI_ID Umami analytics tracking ID abc123def-456
LETTERSPACE_API_URL Letterspace API endpoint https://api.letterspace.com/v1
LETTERSPACE_API_KEY Letterspace authentication key sk_live_...
LETTERSPACE_LIST_ID Mailing list identifier list_abc123
PORT Application port (inside container) 3000
HOST Host binding 0.0.0.0
NODE_ENV Node environment production

Health Checks

The container includes a built-in health check that pings the HTTP server every 30 seconds:

# Check container health
docker inspect --format='{{.State.Health.Status}}' sexy-pivoine-frontend

# View health check logs
docker inspect --format='{{json .State.Health}}' sexy-pivoine-frontend | jq

Logs and Debugging

View Container Logs

# Follow logs
docker logs -f sexy-pivoine-frontend

# Last 100 lines
docker logs --tail 100 sexy-pivoine-frontend

# With timestamps
docker logs -f --timestamps sexy-pivoine-frontend

Execute Commands in Running Container

# Open shell
docker exec -it sexy-pivoine-frontend sh

# Check Node.js version
docker exec sexy-pivoine-frontend node --version

# Check environment variables
docker exec sexy-pivoine-frontend env

Debug Build Issues

# Build with no cache
docker build --no-cache -t sexy.pivoine.art:latest .

# Build specific stage for debugging
docker build --target builder -t sexy.pivoine.art:builder .

# Inspect builder stage
docker run -it --rm sexy.pivoine.art:builder sh

Production Best Practices

1. Use Specific Tags

# Tag with version
docker build -t sexy.pivoine.art:1.0.0 .
docker tag sexy.pivoine.art:1.0.0 sexy.pivoine.art:latest

2. Image Scanning

# Scan for vulnerabilities (requires Docker Scout or Trivy)
docker scout cves sexy.pivoine.art:latest

# Or with Trivy
trivy image sexy.pivoine.art:latest

3. Resource Limits

docker run -d \
  --name sexy-pivoine-frontend \
  -p 3000:3000 \
  --memory="2g" \
  --cpus="2" \
  --env-file .env.production \
  sexy.pivoine.art:latest

4. Restart Policies

docker run -d \
  --name sexy-pivoine-frontend \
  --restart=unless-stopped \
  -p 3000:3000 \
  --env-file .env.production \
  sexy.pivoine.art:latest

5. Use Docker Secrets (Docker Swarm)

# Create secrets
echo "your-api-key" | docker secret create letterspace_api_key -

# Deploy with secrets
docker service create \
  --name sexy-pivoine-frontend \
  --secret letterspace_api_key \
  -p 3000:3000 \
  sexy.pivoine.art:latest

Optimization Tips

Reduce Build Time

  1. Use BuildKit cache mounts (already enabled in Dockerfile)
  2. Leverage layer caching - structure Dockerfile to cache dependencies
  3. Use .dockerignore - exclude unnecessary files from build context

Reduce Image Size

Current optimizations:

  • Multi-stage build (builder artifacts not in final image)
  • Production-only dependencies (pnpm install --prod)
  • Minimal base image (node:20.19.1-slim)
  • Only necessary build artifacts copied to runner

Image size breakdown:

docker images sexy.pivoine.art:latest

CI/CD Integration

GitHub Actions (Automated)

This repository includes automated GitHub Actions workflows for building, scanning, and managing Docker images.

Pre-configured workflows:

  • Build & Push (.github/workflows/docker-build-push.yml)

    • Automatically builds and pushes to ghcr.io/valknarxxx/sexy
    • Triggers on push to main/develop, version tags, and PRs
    • Multi-platform builds (AMD64 + ARM64)
    • Smart tagging: latest, branch names, semver, commit SHAs
  • Security Scan (.github/workflows/docker-scan.yml)

    • Daily vulnerability scans with Trivy
    • Reports to GitHub Security tab
    • Scans on every release
  • Cleanup (.github/workflows/cleanup-images.yml)

    • Weekly cleanup of old untagged images
    • Keeps last 10 versions

Using pre-built images:

# Pull latest from GitHub Container Registry
docker pull ghcr.io/valknarxxx/sexy:latest

# Pull specific version
docker pull ghcr.io/valknarxxx/sexy:v1.0.0

# Run the image
docker run -d -p 3000:3000 --env-file .env.production ghcr.io/valknarxxx/sexy:latest

Triggering builds:

# Push to main → builds 'latest' tag
git push origin main

# Create version tag → builds semver tags
git tag v1.0.0 && git push origin v1.0.0

# Pull request → builds but doesn't push

See .github/workflows/README.md for detailed workflow documentation.

Troubleshooting

Build Fails at Rust Installation

Problem: Rust installation fails or times out

Solution:

  • Check internet connectivity
  • Use a Rust mirror if in restricted network
  • Increase build timeout

WASM Build Fails

Problem: wasm-bindgen-cli version mismatch

Solution:

# In Dockerfile, pin wasm-bindgen-cli version
RUN cargo install wasm-bindgen-cli --version 0.2.103

Container Exits Immediately

Problem: Container starts then exits

Solution: Check logs and verify:

docker logs sexy-pivoine-frontend

# Verify build output exists
docker run -it --rm sexy.pivoine.art:latest ls -la packages/frontend/build

Port Already in Use

Problem: Port 3000 already bound

Solution:

# Use different host port
docker run -d -p 8080:3000 sexy.pivoine.art:latest

Maintenance

Clean Up

# Remove stopped containers
docker container prune

# Remove unused images
docker image prune -a

# Remove build cache
docker builder prune

# Complete cleanup (use with caution)
docker system prune -a --volumes

Update Base Image

Regularly update the base Node.js image:

# Pull latest Node 20 LTS
docker pull node:20.19.1-slim

# Rebuild
docker build --pull -t sexy.pivoine.art:latest .