Files
backup-tool/openspec/changes/dockerize-and-pyproject-setup/design.md
T
alex cc694e71b4 feat: dockerize app and convert to pyproject setup
- Add pyproject.toml with proper metadata and dependency groups
- Create multi-stage Dockerfile for backend
- Add docker-compose.yml with dev/prod profiles
- Create frontend Dockerfile with nginx
- Add .dockerignore for optimized builds
- Update README with Docker instructions and troubleshooting
- Remove requirements.txt in favor of pyproject.toml
- Ensure data persistence with Docker volumes
2026-05-11 22:50:11 +02:00

3.9 KiB

Context

The backup tool currently uses a flat requirements.txt for Python dependencies and requires manual setup (venv, pip install, npm install). There is no standardized deployment method, making it difficult to run in production or share with team members. The codebase needs modern Python packaging and containerization for reliable, repeatable deployments.

Current state:

  • backend/requirements.txt with pinned versions
  • Manual venv creation and dependency installation
  • No Dockerfile or docker-compose setup
  • Frontend served via Vite dev server in development

Goals / Non-Goals

Goals:

  • Replace requirements.txt with a standard pyproject.toml with proper project metadata
  • Add multi-stage Dockerfile for the backend
  • Add docker-compose.yml to orchestrate backend + frontend + optional services
  • Support both development (volume mounts, hot reload) and production (optimized builds) modes
  • Maintain backward compatibility with existing manual setup

Non-Goals:

  • No changes to application code or API behavior
  • No database migration (SQLite remains file-based)
  • No Kubernetes or cloud-specific deployment configs
  • No changes to frontend build tooling

Decisions

1. Poetry vs setuptools for pyproject.toml

  • Decision: Use setuptools with pyproject.toml (PEP 621)
  • Rationale: Simpler, no additional tool dependency. setuptools is mature and widely supported. Poetry adds complexity without clear benefit for this project size.
  • Alternative considered: Poetry - rejected to avoid adding a new tool dependency

2. Multi-stage Dockerfile

  • Decision: Use multi-stage build with separate builder and runtime stages
  • Rationale: Smaller final image, faster builds via layer caching. Builder stage installs build dependencies, runtime stage has only necessary files.
  • Alternative considered: Single-stage - rejected due to larger image size

3. Backend-only container vs full-stack

  • Decision: Provide both options via docker-compose profiles
  • Rationale: Default docker-compose up runs full stack. Users can run docker-compose --profile dev up for development with hot reload.
  • Alternative considered: Separate frontend container - included as option but not default

4. Base image choice

  • Decision: python:3.14-slim for runtime, python:3.14 for builder
  • Rationale: Slim reduces attack surface and image size. Full image in builder for compiling native extensions if needed.
  • Alternative considered: Alpine - rejected due to musl libc compatibility issues with some Python packages

5. Frontend serving in Docker

  • Decision: Build frontend in Docker and serve via backend static files in production
  • Rationale: Single container to deploy. In development, use Vite dev server with proxy.
  • Alternative considered: Separate nginx container - rejected to keep deployment simple

Risks / Trade-offs

  • [Risk] Python 3.14 compatibility: Some dependencies may not have pre-built wheels for Python 3.14

    • Mitigation: Use slim image, test build early, pin compatible versions
  • [Risk] Docker image size: Including Node.js for frontend build increases image size

    • Mitigation: Multi-stage build ensures Node.js tooling is not in final image
  • [Risk] File permissions with SQLite: Container user may not have write access to SQLite DB file

    • Mitigation: Create volume for data directory, set proper user/permissions in Dockerfile

Migration Plan

  1. Create pyproject.toml with all dependencies from requirements.txt
  2. Create Dockerfile and docker-compose.yml
  3. Test build locally with docker compose up
  4. Verify all tests pass in container
  5. Update README with Docker instructions
  6. Keep requirements.txt temporarily, mark as deprecated
  7. After validation, remove requirements.txt

Open Questions

  • Should we add a healthcheck endpoint to docker-compose?
  • Do we need docker-compose override files for different environments?