Docker for Development
The Evolution of Our Development Environment
When we started developing NotionAiAssistant, we quickly realized that a consistent and easy-to-set-up development environment would be essential for the project's success, especially as an open-source initiative aiming to attract contributors.
graph LR
subgraph "Before: Fragmented Development"
PL["Local<br>Python"] --> P1["Environment<br>Inconsistencies"]
PL --> P2["Different<br>Versions"]
P3["Complex<br>Setup"]
end
subgraph "After: Unified Docker"
DC["Docker<br>Compose"] --> B1["Hot<br>Reload"]
DC --> B2["Synced<br>Volumes"]
DC --> B3["Consistent<br>Environment"]
end
I["Developer"] --> A
I --> D
A -.-> |Evolution| D
classDef before fill:#ffcccc,stroke:#333,stroke-width:2px
classDef after fill:#ccffcc,stroke:#333,stroke-width:2px
classDef dev fill:#bbf,stroke:#333,stroke-width:2px
class A,PL,P1,P2,P3 before
class D,DC,B1,B2,B3 after
class I dev
The Initial Challenge: Local Python Development
Initially, our development workflow was fragmented:
- Python running locally on the developer's machine
- PostgreSQL database in a separate Docker container
- Streamlit frontend in another local process
This model presented several problems:
- Environment inconsistencies: "It works on my machine" was a recurring issue
- Complex setup: New contributors had to follow detailed instructions
- Different dependency versions: Caused hard-to-track bugs
- High technical knowledge requirement: Barrier for less experienced contributors
The Solution: Hot Reload in Docker for Development
Our major evolution was implementing a Docker development environment with integrated hot reload:
# Excerpt from our Dockerfile.dev
FROM python:3.10-slim as dev
WORKDIR /app
# Install dependencies with uv for faster speed
COPY requirements-dev.txt .
RUN pip install --no-cache-dir uv
RUN uv pip install --no-cache-dir -r requirements-dev.txt
# Hot reload configuration
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# Entry point that starts the app with hot reload
ENTRYPOINT ["python", "-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080", "--reload"]
Combined with volume mapping in docker-compose:
# Excerpt from docker-compose.dev.yml
services:
app:
build:
context: .
target: dev
volumes:
- ./app:/app/app
- ./config:/app/config
# ...
Transformative Benefits
This approach brought extraordinary benefits:
1. Amplified Productivity
- Automatic hot reload: Code changes are instantly reflected in the browser
- Immediate feedback: Developers see results without restarting containers
- Continuous workflow: Fewer interruptions, more productivity
2. Simplified Experience for Contributors
- Single command to start:
docker-compose -f docker-compose.dev.yml up - No complex local setup: Everything works inside the container
- Consistent environment: All developers have exactly the same setup
3. Accessibility for Different Experience Levels
- Python developers: Can contribute without deep Docker knowledge
- Beginner developers: Significantly reduced entry barrier
- Non-technical contributors: Can easily test and provide feedback
How It Works in Practice
The workflow became incredibly simple:
-
Clone the repository:
git clone https://github.com/your-username/NotionAiAssistant.git cd NotionAiAssistant -
Start the development environment:
docker-compose -f docker-compose.dev.yml up -
Start developing:
- Edit files in your favorite IDE
- Changes are detected automatically
- The app reloads in seconds
- See changes in the browser in real-time
Before and After Comparison
| Aspect | Before | After |
|---|---|---|
| Time to start | 5-10 minutes | 1-2 minutes |
| Initial setup | Complex, multiple steps | Single command |
| Feedback after changes | 30-60 seconds | 1-2 seconds |
| Consistency among devs | Variable | 100% consistent |
| Contribution barrier | High | Low |
Lessons and Best Practices
Our experience taught us some valuable practices:
- Prioritize developer experience from the start of the project
- Optimize feedback time - the faster, the better
- Simplify onboarding for new contributors
- Document clearly the development workflow
- Test your environment with developers of different experience levels
Impact on the Project
Implementing hot reload in Docker fundamentally transformed our project:
- Increased contributions: More people could participate easily
- Faster development cycles: Features implemented in less time
- Better code quality: More iterations and experimentation
- More engaged community: Reduced barrier to participation
This approach became one of the pillars of our project's philosophy: advanced technology that feels simple for the end user.
"The best tool isn't the one with the most features, but the one that removes obstacles from your path."