Docker & Compose
Image
The Dockerfile is a multi-stage build:
- build —
mcr.microsoft.com/dotnet/sdk:10.0restores and publishessrc/BookmarksManager.Api, stamping the assembly with the version supplied by CI (see CI/CD). - runtime —
mcr.microsoft.com/dotnet/aspnet:10.0, running as a non-rootbookmarksuser, listening on port8080.
Published images live at ghcr.io/guibranco/bookmarks-manager-api, tagged with the full SemVer (e.g. 1.2.3), the major.minor.patch (1.2), and latest.
Running it standalone
1
2
3
4
5
6
7
docker run -p 8080:8080 \
-e ApiKey="a-long-random-secret" \
-e Database__Provider=MariaDb \
-e Database__MariaDbServerVersion=10.11.6-mariadb \
-e ConnectionStrings__Default="Server=db;Database=bookmarks_manager;User=bookmarks;Password=change-me;" \
-e Cors__AllowedOrigins__0="https://bookmarks.straccini.com" \
ghcr.io/guibranco/bookmarks-manager-api:latest
Production stack
The repository’s docker-compose.yml runs two services on the production host:
api— the container above, only exposed on the internalbookmarksnetnetwork, with a/health-based healthcheck.nginx— terminates TLS and reverse-proxiesapi.bookmarks.straccini.comto theapiservice. Its config lives atdeploy/nginx/bookmarks-manager-api.confand expects certificates managed bycertbot/Let’s Encrypt under/etc/letsencrypt.
1
2
3
4
# on the production host
cp .env.example .env # fill in BOOKMARKS_MANAGER_API_KEY, connection string, frontend origin
docker compose pull
docker compose up -d
Required environment variables (see docker-compose.yml):
| Variable | Purpose |
|---|---|
BOOKMARKS_MANAGER_API_KEY |
Value for the X-Api-Key header — keep this secret |
BOOKMARKS_MANAGER_CONNECTION_STRING |
MariaDB connection string |
MARIADB_SERVER_VERSION |
MariaDB version string for Pomelo (defaults to 10.11.6-mariadb) |
FRONTEND_ORIGIN |
Browser origin allowed by CORS (the Bookmarks Manager UI’s URL) |
Database migrations
Migrations are provider-specific (BookmarksManager.Migrations.Sqlite / BookmarksManager.Migrations.MariaDb) and are applied out-of-band, before rolling out a new image:
1
2
3
4
EF_PROVIDER=MariaDb dotnet ef database update \
--project src/BookmarksManager.Migrations.MariaDb \
--startup-project src/BookmarksManager.Api \
--connection "Server=db;Database=bookmarks_manager;User=bookmarks;Password=change-me;"
Applying migrations is intentionally decoupled from container startup, so a rollout never races a schema change against multiple starting replicas.