Docker Deployment
The official image bundles LightAPI, its async extras, and PostgreSQL drivers. Mount a YAML config and a database URL — no Python code or build step required.
iklob1/lightapi:latest
iklob1/lightapi:<version> # e.g. 0.1.21
iklob1/lightapi:master # rolling head of master
The image is multi-arch (linux/amd64, linux/arm64) and is built from the
Dockerfile
at the repository root.
Quickstart
-
Write a config file (
lightapi.yaml): -
Start the container:
-
Use the API:
That's the whole flow — no pip install, no manual LightApi(...). The
container reads /app/lightapi.yaml on start, builds the app, and starts
uvicorn on port 8000.
Configuration surface
Mount points
| Path | Purpose |
|---|---|
/app/lightapi.yaml |
Your endpoint config (the only required mount). |
/app/data.db |
Suggested location for an on-disk SQLite database (mount a volume to persist it). |
Environment variables
| Variable | Default | Description |
|---|---|---|
LIGHTAPI_CONFIG |
/app/lightapi.yaml |
Override the config path. |
LIGHTAPI_HOST |
0.0.0.0 |
Uvicorn bind address. |
LIGHTAPI_PORT |
8000 |
Uvicorn port. |
LIGHTAPI_LOG_LEVEL |
info |
debug, info, warning, error. |
DATABASE_URL |
— | Substituted into ${DATABASE_URL} in your YAML. |
LIGHTAPI_JWT_SECRET |
— | Required when your config enables JWT authentication. |
LIGHTAPI_REDIS_URL |
redis://localhost:6379/0 |
Used when Cache(...) is configured. |
Any other ${VAR} placeholder in the YAML is resolved against the
container environment at startup.
Examples
SQLite + persistent volume
docker volume create lightapi-data
docker run -d --name lightapi \
-p 8000:8000 \
-v "$(pwd)/lightapi.yaml:/app/lightapi.yaml:ro" \
-v lightapi-data:/app \
-e DATABASE_URL=sqlite:////app/data.db \
iklob1/lightapi:latest
PostgreSQL via docker compose
# docker-compose.yml
services:
api:
image: iklob1/lightapi:latest
ports:
- "8000:8000"
environment:
DATABASE_URL: postgresql+asyncpg://api:apipass@db:5432/api
LIGHTAPI_JWT_SECRET: replace-me-in-production
volumes:
- ./lightapi.yaml:/app/lightapi.yaml:ro
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: api
POSTGRES_PASSWORD: apipass
POSTGRES_DB: api
healthcheck:
test: ["CMD", "pg_isready", "-U", "api"]
interval: 5s
retries: 5
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
When database.url resolves to a postgresql+asyncpg://... URL, LightAPI
auto-detects the async engine and serves every endpoint asynchronously.
Redis cache
docker run --rm -p 8000:8000 \
-v "$(pwd)/lightapi.yaml:/app/lightapi.yaml:ro" \
-e DATABASE_URL=sqlite:////app/data.db \
-e LIGHTAPI_REDIS_URL=redis://redis:6379/0 \
--network my-net \
iklob1/lightapi:latest
If Redis is unreachable, LightAPI logs a RuntimeWarning once at startup
and falls back to serving from the database — your endpoints keep working.
JWT authentication
# lightapi.yaml
database:
url: "${DATABASE_URL}"
defaults:
authentication:
backend: JWTAuthentication
permission: IsAuthenticated
endpoints:
- route: /books
fields:
title: { type: str }
author: { type: str }
meta:
methods: [GET, POST, PUT, DELETE]
auth:
login_validator: myapp.auth.validate_login
docker run --rm -p 8000:8000 \
-v "$(pwd)/lightapi.yaml:/app/lightapi.yaml:ro" \
-v "$(pwd)/myapp:/app/myapp:ro" \
-e PYTHONPATH=/app \
-e DATABASE_URL=sqlite:////app/data.db \
-e LIGHTAPI_JWT_SECRET=replace-me \
iklob1/lightapi:latest
POST /auth/login is auto-registered because at least one endpoint declares
JWTAuthentication. See
Authentication for the credential-validator
contract.
Custom image
If you need extra Python dependencies (a custom login_validator, custom
middleware, etc.), extend the published image:
FROM iklob1/lightapi:0.1.21
# Add your own modules — they must be importable from the YAML's dotted paths.
COPY ./myapp /app/myapp
ENV PYTHONPATH=/app
# Add any extra Python deps.
RUN pip install --no-cache-dir requests redis
Image build internals
The Dockerfile uses python:3.12-slim, installs LightAPI with the async
extra plus PostgreSQL drivers, drops privileges to a non-root lightapi
user, and ships a small entrypoint (docker/entrypoint.py) that:
- Resolves the config path (
LIGHTAPI_CONFIG, default/app/lightapi.yaml). - Calls
LightApi.from_config(path). - Calls
app.build_app()and runs uvicorn withproxy_headers=Trueandforwarded_allow_ips="*"so reverse-proxy headers (X-Forwarded-For,X-Forwarded-Proto) are honoured.
To build the image locally:
git clone https://github.com/iklobato/LightAPI.git
cd LightAPI
docker build --build-arg LIGHTAPI_VERSION=0.1.21 -t lightapi:local .
Publishing pipeline
master pushes and every v*.*.* tag trigger
.github/workflows/docker-publish.yml, which builds the multi-arch image
and pushes to Docker Hub. The workflow needs two repository secrets:
| Secret | Value |
|---|---|
DOCKERHUB_USERNAME |
Your Docker Hub username (iklob1). |
DOCKERHUB_TOKEN |
A Docker Hub access token with read+write scope on iklob1/lightapi. |
Tag schedule:
| Event | Tags pushed |
|---|---|
Push of v0.1.21 |
iklob1/lightapi:0.1.21, :0.1, :latest |
Push to master |
iklob1/lightapi:master |
Manual workflow_dispatch |
iklob1/lightapi:manual-<run-number> |