From 80fe7a99f0417e3a6a13ad3ff2b2c49b854005ac Mon Sep 17 00:00:00 2001 From: Andrew nuark G Date: Sun, 15 Mar 2026 15:02:08 +0700 Subject: [PATCH] feat: add Docker configuration for containerized deployment --- .dockerignore | 54 ++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 38 ++++++++++++++++++++++++++++++++ README.md | 41 +++++++++++++++++++++++++++++++++++ docker-compose.yml | 40 ++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..208d7f8 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,54 @@ +# Python +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python +.env/ +.venv/ +env/ +venv/ +ENV/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# IDE +.idea/ +.vscode/ +*.swp +*.swo +*~ + +# Project specific +output/*.tif +data/*.tif +data/*.shp +data/*.shx +data/*.dbf +data/*.prj +*.dbf +*.shp +*.shx +*.prj + +# OS +.DS_Store +Thumbs.db + +# Testing +.pytest_cache/ +.coverage +htmlcov/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ddc9513 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,38 @@ +# GIS Classification - Docker Image +FROM python:3.11-slim + +# Set working directory +WORKDIR /app + +# Install system dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + gdal-bin \ + libgdal-dev \ + libgeos-dev \ + libproj-dev \ + && rm -rf /var/lib/apt/lists/* + +# Set GDAL environment variables +ENV GDAL_VERSION=3.6.2 + +# Copy requirements first for better caching +COPY requirements.txt . + +# Install Python dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Copy application code +COPY . . + +# Create necessary directories +RUN mkdir -p /app/data /app/output /app/static + +# Expose port +EXPOSE 8000 + +# Set environment variables +ENV PYTHONUNBUFFERED=1 +ENV PYTHONDONTWRITEBYTECODE=1 + +# Run the application +CMD ["uvicorn", "src.api:app", "--host", "0.0.0.0", "--port", "8000"] diff --git a/README.md b/README.md index a9dc900..0f77a15 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ Python project for land cover classification using GIS data (GeoTIFF + Shapefile gis-classification/ ├── main.py # Main script with parameters ├── requirements.txt # Dependencies +├── Dockerfile # Docker image configuration +├── docker-compose.yml # Docker Compose configuration +├── .dockerignore # Docker ignore rules ├── data/ # Input data folder ├── output/ # Classification results ├── static/ # Web frontend @@ -33,6 +36,44 @@ Or with uv: uv pip install -r requirements.txt ``` +### Docker Deployment + +**Build and run with Docker Compose:** + +```bash +docker-compose up --build +``` + +**Or run with Docker directly:** + +```bash +docker build -t gis-classification . +docker run -p 8000:8000 -v $(pwd)/data:/app/data -v $(pwd)/output:/app/output gis-classification +``` + +Then open http://localhost:8000 in your browser. + +**Production with Nginx (optional):** + +1. Uncomment the nginx section in `docker-compose.yml` +2. Create `nginx.conf` (see example below) +3. Run `docker-compose up -d` + +Example `nginx.conf`: +```nginx +events { worker_connections 1024; } +http { + server { + listen 80; + location / { + proxy_pass http://gis-classification:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + } +} +``` + ## Usage ### CLI Mode diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..9d31900 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,40 @@ +version: '3.8' + +services: + gis-classification: + build: + context: . + dockerfile: Dockerfile + container_name: gis-classification + ports: + - "8000:8000" + volumes: + # Mount data directory for input files + - ./data:/app/data + # Mount output directory for results + - ./output:/app/output + # Mount static files (frontend) + - ./static:/app/static + environment: + - PYTHONUNBUFFERED=1 + # Optional: Set max upload size (in bytes) + - MAX_UPLOAD_SIZE=104857600 + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + +# Optional: Add nginx reverse proxy for production +# nginx: +# image: nginx:alpine +# container_name: gis-nginx +# ports: +# - "80:80" +# volumes: +# - ./nginx.conf:/etc/nginx/nginx.conf:ro +# depends_on: +# - gis-classification +# restart: unless-stopped