Files
Akern-Genai/DOCKER.md
Matteo Rosati 7df1b9f718 dockerize app
2026-01-20 10:46:14 +01:00

216 lines
4.7 KiB
Markdown

# Docker Setup Guide
This document explains how to build and run the Akern-Genai application using Docker.
## Overview
The Docker configuration includes:
- **Multi-stage build** for smaller image size
- **Entrypoint script** with proper signal handling and exit status management
- **Configurable port** via environment variables
- **Health checks** for monitoring
- **Non-root user** for security
- **Optimized build** with `.dockerignore`
## Files
- [`Dockerfile`](Dockerfile) - Multi-stage Docker build configuration
- [`entrypoint.sh`](entrypoint.sh) - Entrypoint script with signal handling
- [`docker-compose.yml`](docker-compose.yml) - Docker Compose configuration
- [`.dockerignore`](.dockerignore) - Files excluded from Docker build context
## Environment Variables
The following environment variables can be configured:
| Variable | Default | Description |
| ----------- | --------- | ----------------------------------------------------- |
| `PORT` | `8000` | Port on which the application listens |
| `HOST` | `0.0.0.0` | Host address to bind to |
| `WORKERS` | `1` | Number of uvicorn worker processes |
| `LOG_LEVEL` | `info` | Logging level (debug, info, warning, error, critical) |
## Building the Image
### Using Docker directly:
```bash
docker build -t akern-genai:latest .
```
### Using Docker Compose:
```bash
docker-compose build
```
## Running the Container
### Using Docker directly:
```bash
# Run with default configuration (port 8000)
docker run -p 8000:8000 akern-genai:latest
# Run with custom port
docker run -p 3000:3000 -e PORT=3000 akern-genai:latest
# Run with multiple workers
docker run -p 8000:8000 -e WORKERS=4 akern-genai:latest
# Run with custom log level
docker run -p 8000:8000 -e LOG_LEVEL=debug akern-genai:latest
```
### Using Docker Compose:
```bash
# Run with default configuration
docker-compose up
# Run with custom port
PORT=3000 docker-compose up
# Run in detached mode
docker-compose up -d
# Stop the container
docker-compose down
```
### Using environment file:
Create a `.env` file in the project root:
```env
PORT=8000
HOST=0.0.0.0
WORKERS=1
LOG_LEVEL=info
```
Then run:
```bash
docker-compose up
```
## Signal Handling
The entrypoint script properly handles termination signals:
- **SIGTERM** - Graceful shutdown (sent by `docker stop`)
- **SIGINT** - Interrupt signal (Ctrl+C)
The script will:
1. Forward the signal to uvicorn
2. Wait up to 30 seconds for graceful shutdown
3. Force kill if shutdown doesn't complete in time
4. Exit with the same status code as uvicorn
## Health Check
The container includes a health check that monitors the application:
- **Interval**: 30 seconds
- **Timeout**: 10 seconds
- **Start period**: 5 seconds
- **Retries**: 3
Check container health:
```bash
docker ps
docker inspect <container_id> | grep -A 10 Health
```
## Multi-Stage Build
The Dockerfile uses a two-stage build:
### Stage 1: Builder
- Installs build dependencies (gcc, musl-dev, etc.)
- Creates a virtual environment
- Installs Python dependencies
### Stage 2: Runtime
- Uses minimal Alpine Linux
- Only includes runtime dependencies
- Copies the virtual environment from builder
- Runs as non-root user
This results in a significantly smaller final image.
## Security Features
- **Non-root user**: Application runs as `appuser` (UID 1000)
- **Minimal base image**: Alpine Linux with only necessary packages
- **No build tools in runtime**: Compiler and build tools are not included in final image
## Troubleshooting
### Container exits immediately
Check logs:
```bash
docker logs <container_id>
```
### Port already in use
Change the port:
```bash
docker run -p 3000:3000 -e PORT=3000 akern-genai:latest
```
### Health check failing
Verify the application is running:
```bash
docker exec -it <container_id> wget -O- http://localhost:8000/
```
### View real-time logs
```bash
docker logs -f <container_id>
```
## Image Size Comparison
- **Before**: ~200-300 MB (single stage with build tools)
- **After**: ~100-150 MB (multi-stage, minimal runtime)
## Production Considerations
For production deployment:
1. **Use specific image tags** instead of `latest`
2. **Set appropriate worker count** based on CPU cores
3. **Configure resource limits** in docker-compose.yml or Kubernetes
4. **Use a reverse proxy** (nginx, traefik) for SSL termination
5. **Set up logging aggregation** (ELK, Loki, etc.)
6. **Configure monitoring** (Prometheus, Grafana)
Example docker-compose.yml with resource limits:
```yaml
services:
app:
deploy:
resources:
limits:
cpus: "2"
memory: 1G
reservations:
cpus: "0.5"
memory: 512M
```