A production-ready multi-container blog platform built with FastAPI, PostgreSQL, and Nginx. Features automated CI/CD pipeline with GitHub Actions, comprehensive testing, and Docker orchestration.
- RESTful API - Full CRUD operations for blog posts
- Database - PostgreSQL with persistent storage
- Reverse Proxy - Nginx for routing and load balancing
- Data Validation - Pydantic models with automatic validation
- API Documentation - Auto-generated interactive docs with Swagger UI
- Containerization - Multi-container orchestration with Docker Compose
- CI/CD Pipeline - Automated testing and deployment with GitHub Actions
- Automated Testing - pytest with FastAPI TestClient
- Container Registry - Automated builds pushed to Docker Hub
The application consists of three services:
┌─────────────┐
│ Client │
└──────┬──────┘
│ HTTP
▼
┌─────────────┐
│ Nginx │ (Reverse Proxy)
│ Port 80 │
└──────┬──────┘
│
▼
┌─────────────┐
│ Backend │ (FastAPI)
│ Port 8000 │
└──────┬──────┘
│
▼
┌─────────────┐
│ PostgreSQL │ (Database)
│ Port 5432 │
└─────────────┘
All services communicate through Docker's internal networking with persistent data storage.
multi-container-blog-platform/
├── .github/
│ └── workflows/
│ └── ci-cd.yml
├── backend/
│ ├── tests/
│ │ ├── __init__.py
│ │ └── test_api.py
│ ├── app.py
│ ├── models.py
│ ├── requirements.txt
│ └── Dockerfile
├── nginx/
│ ├── nginx.conf
│ └── Dockerfile
├── docker-compose.yml
├── .gitignore
└── README.md
- Docker
- Docker Compose
- Git
git clone https://github.com/bookie212/multi-container-blog-platform.git
cd multi-container-blog-platformdocker-compose up --buildThe application will be accessible at http://localhost
Visit http://localhost/docs for interactive API documentation
docker-compose downTo stop and remove volumes (delete all data):
docker-compose down -vYou can also run the application using pre-built images from Docker Hub:
# Pull the latest images
docker pull bookie212/my-backend:latest
docker pull bookie212/my-nginx:latest
# Run with docker-compose
docker-compose upCreate a new blog post.
Request body:
{
"title": "Post Title",
"content": "Post content here",
"author": "Author Name"
}Response: 201 Created
{
"id": 1,
"title": "Post Title",
"content": "Post content here",
"author": "Author Name",
"created_at": "2024-11-26T12:00:00"
}Returns a list of all blog posts.
Response: 200 OK
[
{
"id": 1,
"title": "Post Title",
"content": "Post content here",
"author": "Author Name",
"created_at": "2024-11-26T12:00:00"
}
]Returns a specific blog post by ID.
Parameters: post_id (integer)
Response: 200 OK or 404 Not Found
Updates a specific blog post.
Parameters: post_id (integer)
Request body:
{
"title": "Updated Title",
"content": "Updated content",
"author": "Author Name"
}Response: 200 OK or 404 Not Found
Deletes a specific blog post.
Parameters: post_id (integer)
Response: 200 OK with {"message": "Post deleted successfully"}
FastAPI automatically generates interactive API documentation (Swagger UI).
Access at: http://localhost/docs
curl -X POST http://localhost/posts/ \
-H "Content-Type: application/json" \
-d '{
"title": "My First Post",
"content": "Hello Docker Compose!",
"author": "DevOps Student"
}'curl http://localhost/posts/curl http://localhost/posts/1curl -X PUT http://localhost/posts/1 \
-H "Content-Type: application/json" \
-d '{
"title": "Updated Title",
"content": "Updated content",
"author": "DevOps Student"
}'curl -X DELETE http://localhost/posts/1# Make sure containers are running
docker-compose up -d
# Install dependencies
cd backend
pip install -r requirements.txt
# Run tests
pytest tests/Tests are automatically executed on every push to the repository via GitHub Actions. Check the Actions tab for results.
This project uses GitHub Actions for continuous integration and deployment:
- Push to
masterbranch - Pull requests to
masterbranch
-
Test
- Sets up Python 3.12 environment
- Spins up PostgreSQL test database
- Installs dependencies
- Runs pytest test suite
-
Build and Push (only if tests pass)
- Builds Docker images for backend and nginx
- Tags images with
latestand commit SHA - Pushes images to Docker Hub
- Makes images publicly available
Check the Actions tab to see pipeline runs and results.
Blog post data is persisted using Docker volumes. The PostgreSQL data is stored in the db_data volume:
- ✅ Data survives container restarts
- ✅ Data persists when running
docker-compose down - ❌ Data is deleted with
docker-compose down -v
Test persistence:
# Create a post
curl -X POST http://localhost/posts/ \
-H "Content-Type: application/json" \
-d '{"title": "Test", "content": "Testing persistence", "author": "Tester"}'
# Stop containers
docker-compose down
# Restart containers
docker-compose up -d
# Verify post still exists
curl http://localhost/posts/- FastAPI - Modern, high-performance web framework for building APIs
- Pydantic - Data validation using Python type annotations
- PostgreSQL - Powerful open-source relational database
- psycopg2 - PostgreSQL adapter for Python
- Uvicorn - Lightning-fast ASGI server
- pytest - Testing framework
- httpx - HTTP client for testing
- Nginx - High-performance reverse proxy and web server
- Docker - Containerization platform
- Docker Compose - Multi-container application orchestration
- GitHub Actions - CI/CD automation
- Docker Hub - Container registry
The application uses environment variables for flexible configuration:
In docker-compose.yml:
environment:
POSTGRES_USER: bloguser
POSTGRES_PASSWORD: blogpassword
POSTGRES_DB: blogdbIn CI/CD (GitHub Actions):
DB_HOST: Database hostname (localhost for tests, db for docker-compose)DB_NAME: Database nameDB_USER: Database usernameDB_PASSWORD: Database passwordDB_PORT: Database port
- 80: Nginx (main application entry point)
- 8000: Backend API (direct access, optional)
- 5432: PostgreSQL (for database inspection)
docker-compose logsdocker-compose logs backend
docker-compose logs db
docker-compose logs nginxdocker-compose logs -f backenddocker-compose psdocker-compose restart backendIf you see "could not translate host name" errors:
- Ensure
DB_HOSTenvironment variable is set correctly - For local development: use
localhost - For Docker Compose: use
db
- Check the Actions tab for detailed error logs
- Verify Docker Hub credentials are set in GitHub Secrets
- Ensure all tests pass locally before pushing
Potential improvements for this project:
- Add authentication and authorization (JWT tokens)
- Implement rate limiting
- Add Prometheus and Grafana for monitoring
- Deploy to cloud platform (AWS, DigitalOcean, GCP)
- Add Redis caching layer
- Implement database migrations with Alembic
- Add comprehensive logging with ELK stack
- Set up Kubernetes deployment
- Add end-to-end tests with Selenium
- Implement blue-green deployment strategy
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Bukola - @bookey082
Project Link: [https://github.com/bookie212/multi-container-blog-platform]
⭐ Star this repository if you found it helpful!