Videoflix is a containerized full-stack video streaming application inspired by Netflix.
An Angular frontend communicates via REST API with a Django backend,
both services are operated in isolation and reproducibly using Docker and Docker Compose.
The application supports HLS video streaming, background video processing via RQ workers, Redis caching, and automated deployment via GitHub Actions.
Before running this project, ensure you have:
- Docker installed
- Docker Compose installed
Clone the repository from GitHub
git clone git@github.com:EnsslinAdrian/Videoflix.git videoflixNavigate to the folder
cd videoflixCreate a .env file using this command and fill in the variables:
cp .env.template .envGenerate a Django secret key:
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"Note
Paste the generated key into SECRET_KEY in your .env.
Build the images:
docker compose buildStart the application:
docker compose up -dAccess the frontend:
http://<FRONTEND_VIRTUAL_HOST>
Access the backend API:
http://<BACKEND_VIRTUAL_HOST>/api/
|-- 📁 .github
| |-- 📁 workflows
| | |-- ❕ deployment.yml
|
|-- 📁 videoflix_backend
| |-- 📁 auth_app
| |-- 📁 movie_app
| |-- 📁 videoflix_config
| |-- 📄 .dockerignore
| |-- 📄 .gitignore
| |-- 📄 backend.entrypoint.sh
| |-- 📄 Dockerfile
| |-- 📄 manage.py
| |-- 📄 requirements.txt
|
|-- 📁 videoflix_frontend
| |-- 📁 nginx
| | |-- ⚙️ default.conf
| |-- 📁 src
| |-- 📄 .dockerignore
| |-- 📄 .gitignore
| |-- 📄 angular.json
| |-- 📄 Dockerfile
| |-- 📄 package.json
| |-- 📄 tsconfig.json
|
|-- ⚙️ .env
|-- ⚙️ .env.template
|-- 📄 .gitignore
|-- 📄 docker-compose.yml
|-- ℹ️ README.md
This project uses Docker Compose to orchestrate multiple services: frontend, backend, database, Redis cache, and an RQ background worker.
The docker-compose.yml acts as the orchestrator of this application. It defines all services which share the same internal network.
- frontend # Angular app served via Nginx, built with API_URL injected at build time
- backend # Django REST API served via Gunicorn on port 8000
- db # PostgreSQL 16 database with healthcheck
- redis # Redis 7 cache with password protection
- rq-worker # Background worker for video processing tasks (ffmpeg / HLS conversion)The backend Dockerfile uses a two-stage build to separate dependency installation from the runtime image.
- builder stage # Installs Python dependencies including gcc and libpq-dev
- runtime stage # Copies installed packages into a slim Python 3.12 image
- ffmpeg # Installed for server-side HLS video conversion
- expose # Exposes port 8000 for the Gunicorn application
- entrypoint # Starts the application via backend.entrypoint.shThe entrypoint script prepares and starts the backend at container startup.
- migrations # Applies all pending Django database migrations
- static files # Collects static assets for production usage
- superuser setup # Creates an admin user from environment variables if not exists
- application run # Starts Django via Gunicorn with configurable workers and threadsThe frontend is built using a multi-stage Docker build and served via Nginx.
- build stage # Compiles the Angular application using Node.js 22 Alpine
- config injection # Injects the backend API URL at build time via ARG/ENV
- runtime stage # Copies compiled output into a minimal Nginx Alpine image
- nginx config # Serves the SPA with try_files fallback for Angular routingThe Nginx configuration serves the Angular SPA and handles client-side routing.
- listen # Serves the application on port 80
- try_files # Falls back to index.html for Angular client-side routing
- server_tokens # Hides Nginx version for securityThe GitHub Actions workflow automates building, publishing, and deploying the application on every push to main.
- checkout # Checks out the repository to access Dockerfiles and compose configuration
- registry login # Authenticates to GitHub Container Registry (GHCR) using GITHUB_TOKEN
- frontend build # Builds the Angular image with API_URL injected and pushes to GHCR
- backend build # Builds the Django image and pushes to GHCR (latest + commit SHA tags)
- env provisioning# Creates and secures the .env file on the target VM via SSH
- compose sync # Transfers docker-compose.yml to the remote server via SCP
- deployment # Pulls updated images and recreates containers with Docker Compose
- cleanup # Removes unused Docker images to keep the server cleanStart project
docker compose up -dStop containers
docker compose downRemove containers + volumes
docker compose down -vRestart
docker compose restartRebuild images
docker compose build --no-cacheList running containers
docker psView container logs
docker compose logs -f <service>Execute command inside container
docker compose exec <service> shClear Redis cache
docker compose exec redis redis-cli -a <REDIS_PASSWORD> FLUSHDBView all service logs
docker compose logs -fView backend logs only
docker compose logs -f backendView RQ worker logs
docker compose logs -f rq-workerAdrian Enßlin