fitpub/CONTAINERS.md
Marcus Fihlon ef148ae20e
docs: add and refine project documentation
Signed-off-by: Marcus Fihlon <marcus@fihlon.swiss>
2026-05-02 17:37:27 +02:00

7.2 KiB

Container Deployment Guide

This guide explains how to run FitPub with containers using either Docker or Podman.

The repository ships a docker-compose.yml file. Despite the name, it can also be used with Podman-compatible compose tooling.

Supported runtimes

  • Docker Engine with the docker compose plugin
  • Podman with podman compose or another compatible compose frontend

Examples in this guide use both command styles where that adds clarity:

docker compose ...
podman compose ...

If your environment uses a different compose wrapper, adapt the command prefix accordingly.

Quick start

1. Clone the repository

git clone <repository-url>
cd fitpub

2. Create an environment file

cp .env.example .env

3. Set production values

At minimum, review and set the following values in .env:

SPRING_PROFILES_ACTIVE=prod
POSTGRES_DB=fitpub
POSTGRES_USER=fitpub
POSTGRES_PASSWORD=change-this
APP_PORT=8080
FITPUB_DOMAIN=your-domain.com
FITPUB_BASE_URL=https://your-domain.com
JWT_SECRET=replace-with-a-long-random-secret

Recommended command for generating secrets for values such as JWT_SECRET and POSTGRES_PASSWORD:

openssl rand -base64 64

4. Start the stack

docker compose up -d --build
podman compose up -d --build

5. Verify the deployment

FitPub should become available at:

  • Application: http://localhost:8080 or your configured public URL
  • Health check endpoint: http://localhost:8080/actuator/health

Environment variables used by the container stack

The compose file expects these variables:

Variable Purpose Example / default
SPRING_PROFILES_ACTIVE Spring profile for the app container prod
POSTGRES_DB PostgreSQL database name fitpub
POSTGRES_USER PostgreSQL user fitpub
POSTGRES_PASSWORD PostgreSQL password set explicitly
POSTGRES_PORT Host port for PostgreSQL 5432
APP_PORT Host port for FitPub 8080
FITPUB_DOMAIN Public domain used by the app your-domain.com
FITPUB_BASE_URL Public base URL https://your-domain.com
JWT_SECRET JWT signing secret set explicitly
JWT_EXPIRATION_MS JWT token lifetime 86400000
REGISTRATION_PASSWORD Optional invite-style registration password empty
JPA_SHOW_SQL Enable SQL logging false
JPA_FORMAT_SQL Format SQL logs false
LOG_LEVEL_ROOT Root log level INFO
LOG_LEVEL_APP App log level INFO
LOG_LEVEL_SPRING Spring log level INFO
LOG_LEVEL_HIBERNATE Hibernate log level WARN
LOG_LEVEL_FLYWAY Flyway log level INFO

.env.example documents the application-level environment variables and defaults. The compose file adds a smaller set of container-specific variables around database wiring, ports, and log levels.

Services

postgres

  • Image: postgis/postgis:16-3.4
  • Exposes container port 5432
  • Uses the named volume postgres_data
  • Runs a pg_isready health check

app

  • Built from the repository Dockerfile
  • Exposes container port 8080
  • Uses the named volumes app_uploads and app_logs
  • Waits for the database health check before starting
  • Publishes a health check on /actuator/health

Common operations

Show logs

docker compose logs -f
docker compose logs -f app
docker compose logs -f postgres
podman compose logs -f
podman compose logs -f app
podman compose logs -f postgres

Restart services

docker compose restart
docker compose restart app
podman compose restart
podman compose restart app

Stop and remove the stack

docker compose stop
docker compose down
docker compose down -v
podman compose stop
podman compose down
podman compose down -v

down -v removes persistent volumes and deletes database data.

Run commands inside containers

docker compose exec app bash
docker compose exec postgres psql -U fitpub -d fitpub
podman compose exec app bash
podman compose exec postgres psql -U fitpub -d fitpub

Rebuild the application image

docker compose up -d --build app
docker compose build --no-cache app
podman compose up -d --build app
podman compose build --no-cache app

Volumes and backups

The compose stack creates these named volumes:

  • postgres_data
  • app_uploads
  • app_logs

Examples with Docker:

docker volume ls | grep fitpub
docker volume inspect fitpub_postgres_data
docker run --rm -v fitpub_postgres_data:/data -v "$(pwd)":/backup \
  alpine tar czf /backup/postgres-backup-YYYYMMDD.tar.gz -C /data .

Examples with Podman:

podman volume ls
podman volume inspect fitpub_postgres_data
podman run --rm -v fitpub_postgres_data:/data -v "$(pwd)":/backup \
  docker.io/library/alpine tar czf /backup/postgres-backup-YYYYMMDD.tar.gz -C /data .

Actual volume names can vary with the compose project name. Inspect the stack locally if your names differ.

Health checks and troubleshooting

Application health

curl http://localhost:8080/actuator/health

Database readiness

docker compose exec postgres pg_isready -U fitpub
podman compose exec postgres pg_isready -U fitpub

Check rendered compose configuration

docker compose config
podman compose config

Migration issues

docker compose exec postgres psql -U fitpub -d fitpub -c \
  "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"
podman compose exec postgres psql -U fitpub -d fitpub -c \
  "SELECT * FROM flyway_schema_history ORDER BY installed_rank;"

Reset the stack

docker compose down -v
docker compose up -d --build
podman compose down -v
podman compose up -d --build

This removes all persisted data.

Production notes

  • Set SPRING_PROFILES_ACTIVE=prod
  • Use strong, unique values for POSTGRES_PASSWORD and JWT_SECRET
  • Put FitPub behind HTTPS via a reverse proxy such as nginx, Traefik, or Caddy
  • Back up the database volume regularly
  • Review exposed ports and firewall rules
  • Keep the container runtime and base images updated