Skip to content

Docker Deployment

Deploy Capyshop in productie met Docker Compose, de voorgebouwde containerimage en PostgreSQL met pgvector.

Vereisten

  • Docker Engine 20+
  • Docker Compose v2+

1. Docker Compose Bestand Aanmaken

Maak een docker-compose.yml in je deployment-directory:

yaml
services:
  postgres:
    image: pgvector/pgvector:pg17
    restart: always
    environment:
      POSTGRES_USER: capyshop
      POSTGRES_PASSWORD: changeme
      POSTGRES_DB: capyshop
    volumes:
      - postgres_data:/var/lib/postgresql/data

  app:
    image: capyshop/capyshop:latest
    restart: unless-stopped
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgresql://capyshop:changeme@postgres:5432/capyshop
      - BETTER_AUTH_SECRET=<generate-with-openssl-rand-base64-32>
      - MASTER_SECRET=<generate-with-openssl-rand-base64-32>
      - TRUSTED_ORIGINS=https://mystore.com
      - BASE_URL=https://mystore.com
    volumes:
      - ./data:/app/data
    depends_on:
      - postgres

volumes:
  postgres_data:

Vervang de voorbeeldwaarden:

VariableBeschrijving
BETTER_AUTH_SECRETGeheime sleutel voor sessie-ondertekening. Genereer met openssl rand -base64 32.
MASTER_SECRETApplicatie-hoofdgeheim voor versleuteling. Genereer met openssl rand -base64 32.
POSTGRES_USERPostgreSQL-gebruikersnaam (moet overeenkomen in postgres en DATABASE_URL).
POSTGRES_PASSWORDPostgreSQL-wachtwoord (moet overeenkomen in postgres en DATABASE_URL).
POSTGRES_DBPostgreSQL-databasenaam (moet overeenkomen in postgres en DATABASE_URL).
TRUSTED_ORIGINSKommagescheiden lijst van vertrouwde origins voor CSRF-bescherming en OAuth-redirects (bijv. https://mijnwinkel.nl).
BASE_URLPublieke URL van de winkel, gebruikt in e-mails, SEO, sitemaps (bijv. https://mijnwinkel.nl).

Optioneel: SMTP-configuratie via Omgevingsvariabelen

Standaard worden SMTP-gegevens beheerd via Instellingen → E-mail in het admin-paneel. Als je SMTP liever bij het uitrollen wilt configureren, kun je de onderstaande omgevingsvariabelen instellen. Wanneer ze zijn ingesteld, overschrijven ze de waarden uit het admin-paneel en worden de bijbehorende velden in het E-mailformulier uitgeschakeld.

yaml
environment:
  # ...andere variabelen
  - SMTP_HOST=smtp.sendgrid.net
  - SMTP_PORT=587
  - SMTP_USER=apikey
  - SMTP_PASSWORD=jouw-smtp-wachtwoord
VariableBeschrijving
SMTP_HOSTHostnaam van de mailserver (bijv. smtp.sendgrid.net).
SMTP_PORTPoort van de mailserver. Meestal 587 voor TLS of 465 voor SSL. Moet een geheel getal in [1, 65535] zijn.
SMTP_USERSMTP-inlognaam.
SMTP_PASSWORDSMTP-inlogwachtwoord. Wordt als platte tekst in de omgeving opgeslagen — gaat niet door de versleutelingslaag van de database.

Elke variabele is onafhankelijk. Als alleen SMTP_HOST is ingesteld, blijven de andere drie SMTP-velden bewerkbaar in de admin-interface en worden ze uit de database gelezen.

Optioneel: S3-asset-opslag

Standaard worden geuploade afbeeldingen en andere assets lokaal op schijf opgeslagen onder data/files/. Om uploads naar een S3-compatibele bucket te sturen en vanaf een CDN te serveren, zet je de opslagmodus op s3 en configureer je de bucket-credentials.

yaml
environment:
  # ...andere vars
  - ASSETS_STORAGE_MODE=s3
  - ASSETS_S3_ENDPOINT=https://s3.amazonaws.com
  - ASSETS_S3_REGION=us-east-1
  - ASSETS_S3_BUCKET=my-store-assets
  - ASSETS_S3_ACCESS_KEY_ID=AKIA...
  - ASSETS_S3_SECRET_ACCESS_KEY=...
  - ASSETS_PUBLIC_BASE_URL=https://cdn.mystore.com
  - ASSETS_MAX_BYTES=10gb
VariabeleBeschrijving
ASSETS_STORAGE_MODElocal (standaard) of s3. Bij s3 zijn de zes ASSETS_S3_*-variabelen en ASSETS_PUBLIC_BASE_URL verplicht.
ASSETS_S3_ENDPOINTS3-API-endpoint (bijv. https://s3.amazonaws.com, of de URL van je provider voor Cloudflare R2, Backblaze B2, MinIO, enz.).
ASSETS_S3_REGIONBucket-regio (bijv. us-east-1, auto voor R2).
ASSETS_S3_BUCKETBucketnaam.
ASSETS_S3_ACCESS_KEY_IDAccess key met lees-/schrijfrechten op de bucket.
ASSETS_S3_SECRET_ACCESS_KEYSecret access key.
ASSETS_PUBLIC_BASE_URLPublieke base-URL die de storefront gebruikt om assets te laden (bijv. je CDN-domein dat naar de bucket wijst).
ASSETS_MAX_BYTESOptionele cumulatieve opslaglimiet over alle bestanden. Accepteert 10gb, 500mb of een ruwe byte-telling. Geldt zowel in local- als in s3-modus. Limieten per upload (5 MB afbeelding / 50 MB video) blijven ongewijzigd.

Bij het migreren van een bestaande winkel van local naar s3 voer je het meegeleverde migratiescript een keer uit binnen een uitgerolde container om de bestaande bestanden naar de bucket te uploaden en de WebP-varianten voor te genereren:

bash
docker exec -it <container> node build/scripts/migrate-assets-to-s3.mjs

Het script is idempotent — het opnieuw uitvoeren is veilig en het slaat werk over dat al gedaan is. Als je bestaande originelen op de host staan (bijvoorbeeld /docker/<store>/app_data/files/), bind-mount dat pad dan op /app/data/files binnen de container zodat het script ze kan oppakken; anders valt het terug op wat al in de bucket staat.

2. De Applicatie Starten

bash
docker compose up -d

Dit start twee services:

  • postgres — PostgreSQL 17 met pgvector (pgvector/pgvector:pg17), luisterend op poort 5432.
  • app — De applicatiecontainer (capyshop/capyshop:latest), beschikbaar op poort 3000.

Bij het opstarten voert de applicatiecontainer automatisch databasemigraties uit (prisma migrate deploy) voordat de server wordt gestart.

3. Verifieren

bash
# Controleer of beide containers draaien
docker compose ps

# Bekijk applicatielogs
docker compose logs app

De applicatie zou bereikbaar moeten zijn op http://<jouw-host>:3000.

Reverse Proxy

Voor productie-deployments met HTTPS, plaats een reverse proxy (zoals Traefik, Caddy of nginx) voor de applicatie. De reverse proxy verzorgt TLS-terminatie en stuurt verkeer door naar poort 3000.

Gzip-compressie Inschakelen met Traefik

Als je Traefik als reverse proxy gebruikt, schakel dan gzip-compressie in om de grootte van responses te verkleinen en de laadsnelheid te verbeteren — een factor in de ranking van zoekmachines. Voeg de volgende labels toe aan de app-service in je docker-compose.yml:

yaml
labels:
  - "traefik.http.middlewares.compress.compress.minresponsebodybytes=256"
  - "traefik.http.routers.STORE_NAME-app.middlewares=compress"

Vervang STORE_NAME door de naam van de Traefik-router van je winkel. Het eerste label definieert een compress-middleware die gzip toepast op alle responses groter dan 256 bytes. Het tweede label koppelt die middleware aan de router van je winkel.

Volumes

Volume / MountDoel
postgres_dataBewaart PostgreSQL-gegevens bij het herstarten van containers.
./data:/app/dataBewaart geuploade bestanden en applicatiegegevens bij herstarten.

Bouwen vanuit Broncode

Als je de image liever zelf bouwt in plaats van de voorgebouwde versie te gebruiken:

bash
docker build -t capyshop .

De Dockerfile gebruikt een multi-stage build:

  1. Installeert alle afhankelijkheden en bouwt de applicatie.
  2. Kopieert alleen productie-afhankelijkheden en de build-uitvoer naar de uiteindelijke image.
  3. Voert prisma migrate deploy uit en start vervolgens de server op poort 3000.

Om je eigen image te gebruiken, werk het image-veld bij in je docker-compose.yml, of draai standalone:

bash
docker run -p 3000:3000 \
  -e DATABASE_URL=postgresql://user:pass@host:5432/db \
  -e BETTER_AUTH_SECRET=your-secret \
  -e MASTER_SECRET=your-secret \
  capyshop

Probleemoplossing

FoutOorzaakOplossing
app stopt directOntbrekende of ongeldige omgevingsvariabelenControleer docker compose logs app en verifieer alle vereiste omgevingsvariabelen
ECONNREFUSED naar postgresApp gestart voordat de database gereed wasHerstart de app: docker compose restart app
P3009 - failed migrationsEen eerdere migratie heeft een vervuilde staat gelatenDROP TABLE IF EXISTS _prisma_migrations CASCADE; in de database, herstart daarna
type "vector" does not existpgvector-extensie niet aangemaaktDe pgvector/pgvector:pg17-image bevat deze, maar voer CREATE EXTENSION IF NOT EXISTS vector; uit bij gebruik van een andere image
Poort 3000 al in gebruikEen ander proces gebruikt de poortStop het conflicterende proces of wijzig de poortmapping in docker-compose.yml
Geuploade bestanden weg na herstart./data-volume niet gekoppeldZorg ervoor dat de volumes-sectie ./data:/app/data bevat