This guide explains how to run the Simple Invoicing application using Docker and Docker Compose.
- Docker (version 20.10+)
- Docker Compose (version 1.29+)
Copy the example .env file and update the values:
cp .env.example .envProduction:
docker compose --profile prod up -dDevelopment (with hot-reload):
docker compose --profile dev up -dThis will:
- Create and start a PostgreSQL database
- Build and start the FastAPI backend service (with hot-reload in dev mode)
- Build and start the React frontend service (Nginx in prod, Vite dev server in dev)
| Service | Production | Development |
|---|---|---|
| Frontend | http://localhost | http://localhost:5173 |
| Backend API | http://localhost:8000 | http://localhost:8000 |
| Database | localhost:5432 | localhost:5432 |
docker compose --profile dev exec backend-dev python seed_admin.pydocker compose --profile dev up -dThis starts db, backend-dev, and frontend-dev services. The backend has --reload enabled and source code is mounted as a volume, so changes are reflected immediately. The frontend runs the Vite dev server with hot module replacement on port 5173.
View logs from all services:
docker-compose logs -fView logs from a specific service:
docker-compose logs -f backend
docker-compose logs -f frontend
docker-compose logs -f dbFor production deployment, modify the docker-compose.yml:
-
Backend changes:
- Remove
--reloadflag - Set strong
SECRET_KEY - Use a reverse proxy (nginx/traefik)
- Consider using
gunicorninstead of uvicorn
- Remove
-
Frontend changes:
- Build is already optimized in the Dockerfile
- Nginx is configured for production use
- Static assets are cached for 1 year
-
Database changes:
- Use managed PostgreSQL service (AWS RDS, Heroku, etc.)
- Regular backups
- Strong credentials
Example production update for backend:
CMD ["gunicorn", "app_main:app", "--workers", "4", "--worker-class", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]docker-compose downdocker-compose down -vdocker-compose up -d --builddocker-compose up -d --build backenddocker-compose exec backend bash
docker-compose exec frontend sh
docker-compose exec db psql -U $POSTGRES_USER -d $POSTGRES_DBEnsure the database service is healthy:
docker-compose ps
docker-compose logs dbWait for database to be fully initialized (check healthcheck status).
Check backend logs:
docker-compose logs backendCommon issues:
- Database not ready yet (wait a few seconds)
- Environment variables not set correctly
- Port 8000 already in use
Check frontend logs:
docker-compose logs frontendEnsure the nginx configuration is correct and backend is accessible.
If ports 80, 8000, or 5432 are already in use, modify the ports in docker-compose.yml:
ports:
- "8080:8000" # Map 8080 on host to 8000 in containerCreate a .env file in the project root to override defaults:
# Database
POSTGRES_USER=your_db_user
POSTGRES_PASSWORD=your_db_password
POSTGRES_DB=your_db_name
# Backend
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
SECRET_KEY=your-very-secure-secret-key
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
# Frontend API
VITE_API_BASE_URL=http://localhost:8000/apiThen update docker-compose.yml to use the .env file:
services:
backend:
env_file: .envdocker-compose psdocker inspect simple_invoicing_backend | grep -A 5 '"Health"'docker statsFor more information, refer to: