This guide explains how to deploy and use the AtlasEye application using a single Docker image that contains all three services:
- Backend (FastAPI application)
- Celery Worker (Background task processor)
- Frontend (Next.js web application)
If the image is published to a registry:
docker pull exprays/atlas-app:latestOr build it locally:
docker build -t atlas-app:latest .docker-compose -f docker-compose.single.yml up -dThis will start:
- PostgreSQL database with PostGIS
- Redis message broker
- Atlas Backend (port 8000)
- Atlas Celery Worker
- Atlas Frontend (port 3000)
- Web Interface: http://localhost:3000
- API Documentation: http://localhost:8000/docs
- Backend API: http://localhost:8000/api/v1
The atlas-app:latest image is built using a multi-stage Docker build:
-
Stage 1: Backend Builder
- Base:
python:3.11-slim - Installs geospatial libraries
- Installs Python dependencies
- Copies backend application code
- Base:
-
Stage 2: Frontend Builder
- Base:
node:23-alpine - Installs npm dependencies
- Builds Next.js production bundle
- Base:
-
Stage 3: Final Runtime Image
- Base:
python:3.11-slim - Installs both Node.js and Python runtime
- Copies backend from Stage 1
- Copies frontend from Stage 2
- Single unified image: ~4.5GB
- Base:
The image uses a smart entrypoint script (/app/docker-entrypoint.sh) that can start different services based on the command:
# Start backend
docker run atlas-app:latest backend
# Start celery worker
docker run atlas-app:latest celery
# Start frontend
docker run atlas-app:latest frontend# 1. Start PostgreSQL
docker run -d --name atlas-postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=satellite_change \
-p 5432:5432 \
postgis/postgis:14-3.2
# 2. Start Redis
docker run -d --name atlas-redis \
-p 6379:6379 \
redis:7-alpine
# 3. Start Backend
docker run -d --name atlas-backend \
--link atlas-postgres:postgres \
--link atlas-redis:redis \
-e POSTGRES_SERVER=postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=satellite_change \
-e CELERY_BROKER_URL=redis://redis:6379/0 \
-e CELERY_RESULT_BACKEND=redis://redis:6379/0 \
-e MODEL_PATH=/app/data/models/final_model.pth \
-e LOCAL_STORAGE_PATH=/app/data/images \
-v $(pwd)/data:/app/data \
-p 8000:8000 \
atlas-app:latest backend
# 4. Start Celery Worker
docker run -d --name atlas-celery \
--link atlas-postgres:postgres \
--link atlas-redis:redis \
-e POSTGRES_SERVER=postgres \
-e POSTGRES_USER=postgres \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=satellite_change \
-e CELERY_BROKER_URL=redis://redis:6379/0 \
-e CELERY_RESULT_BACKEND=redis://redis:6379/0 \
-e MODEL_PATH=/app/data/models/final_model.pth \
-e LOCAL_STORAGE_PATH=/app/data/images \
-v $(pwd)/data:/app/data \
atlas-app:latest celery
# 5. Start Frontend
docker run -d --name atlas-frontend \
-e NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1 \
-e NEXT_PUBLIC_MAPBOX_TOKEN=your_token_here \
-p 3000:3000 \
atlas-app:latest frontendUse the provided docker-compose.single.yml:
# Start all services
docker-compose -f docker-compose.single.yml up -d
# View logs
docker-compose -f docker-compose.single.yml logs -f
# Stop all services
docker-compose -f docker-compose.single.yml down
# Stop and remove volumes
docker-compose -f docker-compose.single.yml down -vCreate your own docker-compose.yml:
version: '3.8'
services:
postgres:
image: postgis/postgis:14-3.2
environment:
- POSTGRES_USER=your_user
- POSTGRES_PASSWORD=your_secure_password
- POSTGRES_DB=your_database
volumes:
- postgres_data:/var/lib/postgresql/data/
redis:
image: redis:7-alpine
backend:
image: atlas-app:latest
command: ["backend"]
environment:
- POSTGRES_SERVER=postgres
- POSTGRES_USER=your_user
- POSTGRES_PASSWORD=your_secure_password
- POSTGRES_DB=your_database
- CELERY_BROKER_URL=redis://redis:6379/0
- MODEL_PATH=/app/data/models/final_model.pth
volumes:
- ./data:/app/data
ports:
- "8000:8000"
celery_worker:
image: atlas-app:latest
command: ["celery"]
environment:
- POSTGRES_SERVER=postgres
- CELERY_BROKER_URL=redis://redis:6379/0
volumes:
- ./data:/app/data
frontend:
image: atlas-app:latest
command: ["frontend"]
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8000/api/v1
ports:
- "3000:3000"
volumes:
postgres_data:Create the required data directories:
mkdir -p data/{models,images,training/{before,after,mask},test_data}Place your trained model in:
data/models/final_model.pth
If you don't have a trained model yet, you can train one after starting the services:
docker-compose -f docker-compose.single.yml exec backend \
python -m app.ml.training.train \
--data_dir=/app/data/training \
--checkpoint_dir=/app/data/models \
--num_epochs=50User-uploaded images and processing results are stored in:
data/images/{job_id}/
├── before_{filename}
├── after_{filename}
├── change_visualization.png
├── change_detection.geojson
└── evaluation_metrics.json
| Variable | Description | Default |
|---|---|---|
POSTGRES_SERVER |
PostgreSQL hostname | postgres |
POSTGRES_USER |
Database user | postgres |
POSTGRES_PASSWORD |
Database password | postgres |
POSTGRES_DB |
Database name | satellite_change |
CELERY_BROKER_URL |
Redis URL for Celery | redis://redis:6379/0 |
CELERY_RESULT_BACKEND |
Results backend | redis://redis:6379/0 |
MODEL_PATH |
Path to trained model | /app/data/models/final_model.pth |
LOCAL_STORAGE_PATH |
Image storage path | /app/data/images |
| Variable | Description | Default |
|---|---|---|
NEXT_PUBLIC_API_URL |
Backend API URL | http://localhost:8000/api/v1 |
NEXT_PUBLIC_MAPBOX_TOKEN |
Mapbox access token | (required for maps) |
You can scale the number of workers:
# Scale celery workers to 3 instances
docker-compose -f docker-compose.single.yml up -d --scale celery_worker=3
# Scale backend to 2 instances (requires load balancer)
docker-compose -f docker-compose.single.yml up -d --scale backend=2Add Nginx for load balancing multiple backend instances:
services:
nginx:
image: nginx:alpine
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- backend# Tag the image
docker tag atlas-app:latest exprays/atlas-app:latest
docker tag atlas-app:latest exprays/atlas-app:v1.0.0
# Push to Docker Hub
docker push exprays/atlas-app:latest
docker push exprays/atlas-app:v1.0.0# Login
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
# Tag
docker tag atlas-app:latest ghcr.io/exprays/atlas-app:latest
# Push
docker push ghcr.io/exprays/atlas-app:latestThe image includes health checks for the backend:
# Check backend health
curl http://localhost:8000/health
# Response should be:
# {"status": "healthy"}# Check logs
docker logs atlas-backend
docker logs atlas-celery-worker
docker logs atlas-frontend
# Or with docker-compose
docker-compose -f docker-compose.single.yml logs backend-
Check if backend is running:
curl http://localhost:8000/docs
-
Verify
NEXT_PUBLIC_API_URLin frontend:docker-compose -f docker-compose.single.yml exec frontend env | grep NEXT_PUBLIC
-
For production, update to public URL:
NEXT_PUBLIC_API_URL=https://your-domain.com/api/v1
# Check Celery worker logs
docker-compose -f docker-compose.single.yml logs celery_worker
# Check Redis connection
docker-compose -f docker-compose.single.yml exec redis redis-cli ping
# Should return: PONG
# Restart worker
docker-compose -f docker-compose.single.yml restart celery_worker# Clean up Docker
docker system prune -af --volumes
# Remove old images
docker images | grep atlas-app | awk '{print $3}' | xargs docker rmiCurrent image size: ~4.5GB
The size is large due to:
- PyTorch and CUDA libraries: ~3GB
- Geospatial libraries: ~500MB
- Node.js runtime: ~200MB
- Next.js build: ~200MB
To reduce size:
- Use CPU-only PyTorch build (reduces by ~1.5GB)
- Remove unnecessary dependencies
- Use multi-stage builds more efficiently
- Mount volumes for data: Don't copy large datasets into the image
- Use bind mounts in development: For live code changes
- Use named volumes in production: For data persistence
- Enable GPU support: Add NVIDIA runtime for faster processing
- Scale workers: Add more Celery workers for parallel processing
For production:
- Change default passwords
- Use secrets management (Docker Secrets, Kubernetes Secrets)
- Enable HTTPS with reverse proxy
- Implement authentication on API endpoints
- Limit container resources (memory, CPU)
- Run as non-root user (update Dockerfile)
- Scan images for vulnerabilities:
docker scan atlas-app:latest
For issues or questions:
- GitHub Issues: https://github.com/exprays/Atlas/issues
- Documentation: /DEPLOYMENT_GUIDE.md
- Architecture: /Architecture.md
Version: 1.0.0
Last Updated: December 2025
Maintained by: Exprays