216 lines
4.7 KiB
Markdown
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
|
|
```
|