Docker & Deployment
LIME now has three distinct Docker surfaces:
docker-compose.ymlfor production-style local builds from sourcedocker-compose.dev.ymlas the local development override for UI hot reloaddocker-compose.release.ymlfor published runtime images
The runtime model is intentionally split:
- the UI still reads PostgreSQL directly for server-rendered pages
- Shopkeeper still owns scan actions and API writes
- the browser only talks to the UI origin
- the Next server proxies
/api/...to Shopkeeper at runtime throughSHOPKEEPER_URL
That keeps the Docker images generic. They do not need a build-time public API URL.
Local Docker Stack
The local stack builds from source and keeps the bundled Postgres workflow:
dbshopkeeperui
Use:
make start-db
make migrate-all
make start-shopkeeper
make start-ui
make start-all
make start-dev
make stop-all
The root .env controls:
- published UI and API host ports
- native local-development
DATABASE_URL - native local-development
SHOPKEEPER_URL - bundled Postgres bootstrap values
Important local detail:
- the Docker services override
DATABASE_URLandSHOPKEEPER_URLinternally to use Docker service names (dbandshopkeeper) make start-allbuilds the production UI image and serves the built Next appmake start-devappliesdocker-compose.dev.ymland runs the UI with NextJS hot reloadmake dev-uioverridesSHOPKEEPER_URLtohttp://localhost:<LIME_API_PORT>for native Next development
Production Build Targets
The root Makefile exposes:
make buildfor production artifacts indist/make build-dockerfor local production image builds tagged from VERSIONmake migrate-allto run./shopkeeper --migratein a one-off Shopkeeper container against the local Docker database
Local image names:
lime-shopkeeper:v<version>lime-ui:v<version>
These builds are generic. Runtime deployments must supply:
DATABASE_URLSHOPKEEPER_URL- any published port mapping they want
GitHub Release Publishing
Pushing to main triggers release-docker.yml.
The workflow:
- reads
VERSIONand usesv<VERSION>as the release tag - requires a matching
CHANGELOG.mdsection and uses it as the GitHub Release notes - refuses to overwrite an existing release tag that points at another commit
- installs the repo toolchains and runs
make buildas the release preflight - builds and pushes:
ghcr.io/<repo-owner>/lime-shopkeeper:<release-tag>ghcr.io/<repo-owner>/lime-ui:<release-tag>- also tags both images as
latestandsha-<commit> - uses
scripts/publish-release-images.shfor Docker publish logic - adds OCI labels for source, version, and revision
- uses
scripts/publish-github-release.shto create or update the GitHub Release - uploads a release bundle asset like
lime-v0.1.0-release.tar.gz
No build-time NEXT_PUBLIC_API_URL is used in this workflow anymore.
Release Bundle
The release bundle contains:
docker-compose.release.yml.env.exampleREADME.mddata/*.json
After extracting the bundle:
cp .env.example .env
docker compose --env-file .env -f docker-compose.release.yml up -d
The release stack is external-Postgres only. It ships only:
shopkeeperui
Required runtime env values:
LIME_IMAGE_REGISTRYLIME_IMAGE_TAGDATABASE_URLSHOPKEEPER_URLLIME_API_PORTLIME_UI_PORT
The bundled data directory is mounted into /shared-data so ACT and axe metadata are available without a source checkout.
Runtime URL Model
The browser uses only same-origin UI paths:
- page routes like
/scans/... - API routes like
/api/scans/... - screenshot routes like
/api/screenshots/...
The Next route handler proxies those /api/... requests to SHOPKEEPER_URL at runtime. That means:
- reverse proxies can publish the UI on any external host or port
- the images do not need rebuilding when deployment URLs change
- direct Shopkeeper exposure on
LIME_API_PORTremains optional for debugging or separate service access
Non-Docker Production
make build produces:
dist/shopkeeper/with the compiled binary and migrationsdist/ui/with the Next standalone output- the release bundle archive
For non-Docker deployments, operators must still provide runtime env for:
DATABASE_URLSHOPKEEPER_URL
Because the UI still reads PostgreSQL directly for server-rendered pages, both processes must be able to reach the same database.
Docker Hygiene
Service-level .dockerignore files exclude local-only files such as:
node_modules.next- local env files
- screenshots
- build caches
- editor artifacts
This keeps build contexts small and prevents development noise from leaking into released images.
Shopkeeper Container Note
Shopkeeper still runs Chromium inside Docker, so the container keeps shm_size: 2gb to avoid browser memory issues during scans.