Deploy ThunderID with Docker
This guide walks you through deploying ThunderID using Docker. Run it as a single container with SQLite, or connect it to an external PostgreSQL database for a more durable setup, all without any cluster infrastructure.
Prerequisites
Before you begin, ensure the following tools are installed:
| Tool | Minimum Version | Installation Guide | Version Check |
|---|---|---|---|
| Docker | 20.10 | Install Docker | docker --version |
| Docker Compose | 2.0 | Install Docker Compose | docker compose version |
Verify your installation:
docker --version
docker compose version
docker run hello-world
ThunderID listens on port 8090 by default. Ensure that port is available on your host.
Run ThunderID with Docker
Step 1: Pull the Image
Pin to a specific release tag for reproducible deployments:
docker pull ghcr.io/thunder-id/thunderid:latest
Step 2: Set Up the Server
Run the one-time setup script before starting ThunderID for the first time. It initializes the configuration and database. Mount a named volume for config/certs, where setup generates this deployment's TLS, JWT signing, and encryption keys, and one for config/secrets, where setup writes the Direct Auth Secret, so the server can read them. If you are using SQLite, also mount a volume for the database so it persists:
docker run -it --rm \
-v thunderid-data:/opt/thunderid/database \
-v thunderid-certs:/opt/thunderid/config/certs \
-v thunderid-secrets:/opt/thunderid/config/secrets \
ghcr.io/thunder-id/thunderid:latest \
./setup.sh
The container exits after setup completes. The generated key material is unique to this deployment and is reused on later runs. The server fails to start if it is missing, so always run setup, with the config/certs and config/secrets volumes mounted, before starting the server.
Step 3: Start the Server
Run ThunderID in the background with a restart policy so it recovers from host reboots and unexpected exits:
docker run -d \
--name thunderid \
--restart unless-stopped \
-p 8090:8090 \
-v thunderid-data:/opt/thunderid/database \
-v thunderid-certs:/opt/thunderid/config/certs \
-v thunderid-secrets:/opt/thunderid/config/secrets \
ghcr.io/thunder-id/thunderid:latest
ThunderID is now running at https://localhost:8090. Mount the same thunderid-certs and thunderid-secrets volumes you used during setup so the server reads the generated key material and the Direct Auth Secret.
To follow the logs:
docker logs -f thunderid
Customize the Configuration
To override the default server configuration, mount a custom deployment.yaml file. Create a deployment.yaml based on the default configuration and pass it to the container:
docker run -d \
--name thunderid \
--restart unless-stopped \
-p 8090:8090 \
-v $(pwd)/deployment.yaml:/opt/thunderid/deployment.yaml \
-v thunderid-data:/opt/thunderid/database \
-v thunderid-certs:/opt/thunderid/config/certs \
-v thunderid-secrets:/opt/thunderid/config/secrets \
ghcr.io/thunder-id/thunderid:latest
To also use custom TLS certificates, mount them alongside the configuration:
docker run -d \
--name thunderid \
--restart unless-stopped \
-p 8090:8090 \
-v $(pwd)/deployment.yaml:/opt/thunderid/deployment.yaml \
-v $(pwd)/certs/server.cert:/opt/thunderid/config/certs/server.cert \
-v $(pwd)/certs/server.key:/opt/thunderid/config/certs/server.key \
-v thunderid-data:/opt/thunderid/database \
-v thunderid-certs:/opt/thunderid/config/certs \
-v thunderid-secrets:/opt/thunderid/config/secrets \
ghcr.io/thunder-id/thunderid:latest
The mounted files provide the server TLS certificate; the JWT signing and encryption keys still come from the thunderid-certs volume that setup populated.
Run with Docker Compose
Docker Compose is the recommended way to run ThunderID alongside a PostgreSQL database. Create a docker-compose.yml in your working directory:
services:
thunderid:
image: ghcr.io/thunder-id/thunderid:latest
restart: unless-stopped
ports:
- "8090:8090"
volumes:
- ./deployment.yaml:/opt/thunderid/deployment.yaml
- thunderid-certs:/opt/thunderid/config/certs
- thunderid-secrets:/opt/thunderid/config/secrets
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
restart: unless-stopped
env_file: .env
environment:
POSTGRES_USER: thunderid_user
POSTGRES_DB: configdb
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U thunderid_user"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres-data:
thunderid-certs:
thunderid-secrets:
This snippet runs the server only. Before the first start, run setup once (see Set Up the Server) against the same thunderid-certs and thunderid-secrets volumes so the key material and Direct Auth Secret exist, since the server does not start without them. For a Compose setup that runs the setup step automatically, see the quick-start under install/quick-start.
Create a .env file alongside docker-compose.yml to keep credentials out of version control:
POSTGRES_PASSWORD=<your-database-password>
Start the stack:
docker compose up -d
View logs:
docker compose logs -f
Stop the stack:
docker compose down
Stop and remove all data volumes:
docker compose down -v
Access ThunderID
Once the container is running, access ThunderID at the following endpoints:
| Endpoint | URL |
|---|---|
| Application | https://localhost:8090 |
| Sign-in / Register | https://localhost:8090/signin |
| ThunderID Console | https://localhost:8090/console |
Database Setup
Embedded SQLite (Default)
ThunderID uses SQLite by default. No additional setup is required: it works out of the box with no external dependencies.
Mount a named volume to persist the database across container restarts:
-v thunderid-data:/opt/thunderid/database
External PostgreSQL
For a more durable setup, connect ThunderID to an external PostgreSQL database. ThunderID ships with a Docker Compose file to spin up a PostgreSQL instance alongside the server.
-
Navigate to the
install/local-developmentdirectory:cd install/local-development -
Start PostgreSQL in the background:
docker compose up -d -
View PostgreSQL logs:
docker compose logs -f -
Stop PostgreSQL:
docker compose downTo stop PostgreSQL and delete all data:
docker compose down -v