Payroll Engine Container Setup
This document describes how to set up and run the Payroll Engine stack using Docker.
Setup Variants
The repository includes two Docker Compose files for different use cases:
| File | Use case | Requirement |
|---|---|---|
docker-compose.ghcr.yml |
End users — pulls pre-built images from ghcr.io |
Docker |
docker-compose.yml |
Developers — builds images from local source code | All source repositories present |
The Payroll Console can be run as a Docker container for automation and testing (see Running the Payroll Console below).
Prerequisites
- Docker (includes Docker Compose)
The images are public on the GitHub Container Registry (ghcr.io) — no login or access token is required.
| Image | Platforms |
|---|---|
ghcr.io/payroll-engine/payrollengine.backend |
linux/amd64, linux/arm64 |
ghcr.io/payroll-engine/payrollengine.webapp |
linux/amd64, linux/arm64 |
ghcr.io/payroll-engine/payrollengine.payrollconsole |
linux/amd64, linux/arm64 |
ghcr.io/payroll-engine/payrollengine.mcp.server |
linux/amd64, linux/arm64 |
The SQL Server image (
mcr.microsoft.com/mssql/server) is available forlinux/amd64only. On arm64 hosts (e.g. Apple Silicon) it runs under emulation; the Payroll Engine images run natively.
Getting Started
The stack runs five services: SQL Server, two one-time setup containers (sql-copy extracts the database scripts, db-init creates or migrates the database), the Backend API, and the Web Application. The Payroll Console can be added for automation and testing.
1. Clone the Repository
The repository includes both a developer compose file (docker-compose.yml) and a ready-to-use file for pre-built images:
git clone https://github.com/Payroll-Engine/PayrollEngine.git
cd PayrollEngine
2. Environment Configuration
Create a file named .env in the repository root to set the database password:
# PayrollEngine Docker Stack Configuration
DB_PASSWORD=PayrollStrongPass789
Use alphanumeric characters only — special characters like
!,@,#can cause authentication failures that appear as misleading "sqlcmd not found" errors.The
.envfile is excluded from version control (.gitignore) and must be created manually — this is intentional to avoid storing passwords in the repository.
3. Docker Compose File
The repository includes docker-compose.ghcr.yml — a ready-to-use compose file that pulls pre-built images from ghcr.io. The docker-compose.yml is for local development builds and requires all source repositories to be present.
The
sql-copyservice extracts the database scripts from the Backend image into a shared volume. Thedb-initservice then decides automatically: - New installation: Creates the database and runsModelCreate.sql- Existing database: RunsModelUpdate.sql(skips if already at target version)As a safety net, the Backend verifies the database schema version on startup and refuses to start if the schema is older than the minimum version it supports.
4. Start the Stack
That's it. Steps 1–2 are all that's needed before starting the stack.
docker compose -f docker-compose.ghcr.yml up -d
This will pull the pre-built images from ghcr.io and start all services. On the first run, the database initialization takes approximately 30 seconds.
5. Accessing the Applications
Once the stack is running:
| Service | URL |
|---|---|
| Web Application | http://localhost:8081 |
| Backend API | http://localhost:5001 |
| Swagger UI | http://localhost:5001/swagger |
| SQL Server | localhost:1433 (user: sa, password: from .env) |
Verify the SQL Server connection:
docker exec payroll-db /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P "YourPassword" -C -Q "SELECT @@VERSION"
Use the Payroll Console container to install examples and execute tests against the running Backend.
6. Stopping the Stack
Stop and remove the containers:
docker compose -f docker-compose.ghcr.yml down
Stop and also remove the database volume (all data):
docker compose -f docker-compose.ghcr.yml down -v
Using a Specific Version
By default, docker-compose.ghcr.yml uses the :latest tag. To pin a specific release version, replace the image tags:
sql-copy:
image: ghcr.io/payroll-engine/payrollengine.backend:1.1.0
# ...
backend-api:
image: ghcr.io/payroll-engine/payrollengine.backend:1.1.0
# ...
webapp:
image: ghcr.io/payroll-engine/payrollengine.webapp:1.1.0
# ...
Pin
sql-copyandbackend-apito the same version —sql-copyprovides the database scripts that match the Backend.
Available image tags are listed on the Releases page.
Updating to a New Version
- Update the image tags in
docker-compose.ghcr.yml(or use:latest) - Pull the new images and restart:
docker compose -f docker-compose.ghcr.yml pull docker compose -f docker-compose.ghcr.yml up -d
The db-init service handles database migrations automatically. If the new Backend image includes a schema update, ModelUpdate.sql is executed before the Backend starts. If the database is already at the target version, the script does nothing.
If the Backend detects an unsupported schema version on startup, it will log an error and stop. Check the Release Notes for breaking changes.
Running the Backend Container Standalone
The Backend image contains no database and no connection string. Starting it without configuration — for example via Run in Docker Desktop — fails with:
STARTUP EXCEPTION: Missing database connection string.
To run the Backend against an existing database, pass the connection string as environment variable:
docker run -d --name payroll-backend -p 5001:8080 \
-e ASPNETCORE_URLS="http://+:8080" \
-e PayrollServerConfiguration__EnableSwagger="true" \
-e ConnectionStrings__PayrollDatabaseConnection="Server=host.docker.internal;Database=PayrollEngine;User Id=sa;Password=...;TrustServerCertificate=True;" \
ghcr.io/payroll-engine/payrollengine.backend:latest
For MySQL or PostgreSQL, additionally set the provider (see below):
-e PayrollServerConfiguration__DbProvider="MySql" \
The database must already exist with the Payroll Engine schema. Use
docker-compose.ghcr.ymlfor a complete setup including database initialization.
Running the Payroll Console
The Payroll Console is available as a Docker image for automation, testing, and data import tasks:
docker run --rm --network payroll-engine_default \
-e PayrollApiConnection="BaseUrl=http://backend-api:8080; Port=8080;" \
ghcr.io/payroll-engine/payrollengine.payrollconsole:latest \
PayrollTest --testFile Tests/Test.All.pecmd
Alternative Databases
Besides SQL Server, the Backend supports MySQL 8.0+ (since v1.0, preview) and PostgreSQL 14+ (since v1.1). The provider is selected with PayrollServerConfiguration:DbProvider:
| Provider | DbProvider |
Connection string |
|---|---|---|
| SQL Server | SqlServer (default) |
Server=localhost;Database=PayrollEngine;User Id=sa;Password=...;TrustServerCertificate=True; |
| MySQL | MySql |
Server=localhost;Port=3306;Database=PayrollEngine;User=root;Password=...;CharSet=utf8mb4; |
| PostgreSQL | Postgres |
Host=localhost;Port=5432;Database=PayrollEngine;Username=payroll;Password=...; |
Backend Configuration
Set the database provider in appsettings.json:
"PayrollServerConfiguration": {
"DbProvider": "MySql"
},
"ConnectionStrings": {
"PayrollDatabaseConnection": "Server=localhost;Port=3306;Database=PayrollEngine;User=root;Password=...;CharSet=utf8mb4;"
}
In a container, use the environment variables PayrollServerConfiguration__DbProvider and ConnectionStrings__PayrollDatabaseConnection instead.
Docker Setup
Ready-to-use database containers with automatic schema initialization are included in the Backend repository:
| Database | Folder | Instructions |
|---|---|---|
| MySQL | Database/docker-mysql/ |
Database/docker-mysql/README.md — create and update scenario |
| PostgreSQL | Database/docker-pg/ |
Database/docker-pg/README.md |
These start the database only — run the Backend locally or as a standalone container against it.
Limitations
- MySQL and PostgreSQL are not covered by the standard Docker stack (
docker-compose.ghcr.yml) - The
db-initcontainer currently targets SQL Server only - PostgreSQL has no update script in v1.1 — databases are created with
Create-Model.pg.sql - MySQL support is a preview feature; full production validation is ongoing
Next Steps
- Basic Payroll example
- Examples — payroll examples and demos
- Articles — blog posts and technical articles