Conduit Deployment (Docker & CI/CD)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Quickstart
  4. Environment Variables
  5. CI/CD Deployment
  6. Usage
  7. Logging
  8. Checklist

Introduction

This repository contains the deployment and CI/CD setup for the
Conduit full-stack application (Angular frontend + Django REST backend).

The main focus of this project is:

  • containerization using Docker
  • orchestration with Docker Compose
  • automated build & deployment via GitHub Actions
  • secure handling of configuration and secrets

The frontend and backend are integrated as Git submodules and are built automatically during the CI pipeline.


Project Structure

conduit-deployment/
├── docker-compose.yaml
├── .gitmodules
├── backend/ # Django backend (git submodule)
├── frontend/ # Angular frontend (git submodule)
├── .github/
│ └── workflows/
│ └── deployment.yaml # GitHub Actions CI/CD pipeline
├── .env.template
└── README.md

Quickstart

1. Clone the repository (including submodules)

git clone --recurse-submodules https://github.com/BenjaminTietz/conduit-deployment.git
cd conduit-deployment

If submodules were not cloned:

git submodule update --init --recursive

The submodule configuration does not rely on the default branches of the included repositories


2. Create your environment file

All backend and frontend configuration values are defined in a single .env file located in the project root.

cp .env.template .env

Modify if needed.


3. Start the application locally

docker compose up

docker compose (with a space) is Compose V2, the Docker CLI plugin. The older docker-compose command is Compose V1, which Docker stopped supporting after June 2023. On Debian/Ubuntu the plugin comes from the docker-compose-v2 package, or from docker-compose-plugin in Docker's official repository.

Backend → http://localhost:8000
Frontend → http://localhost:8282


Environment Variables

The container uses .env to configure Django and PostgreSQL:

# =====================
# Frontend (Angular)
# =====================
BACKEND_API_URL=http://backend:8000/api

# =====================
# Backend (Django)
# =====================
DJANGO_SECRET_KEY=changeme
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=*

CORS_ALLOWED_ORIGINS=http://localhost:8282,http://127.0.0.1:8282

POSTGRES_NAME=conduit
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_HOST=db
POSTGRES_PORT=5432

CI/CD Deployment

The deployment pipeline is implemented using GitHub Actions.

Workflow responsibilities:

  • Build frontend and backend Docker images
  • Inject frontend configuration at build time
  • Push images to GitHub Container Registry (GHCR)
  • Deploy containers to a remote VM via SSH
  • Start services using Docker Compose in detached mode

No build steps are executed on the target VM.

This pipeline puts the application on a VM, but it does not set up transport encryption — the NGINX container serves the frontend over plain HTTP and the Django admin login and its session cookie would travel the network unprotected. The missing piece on the VM is a reverse proxy (nginx, Caddy, Traefik) that terminates TLS with a certificate from a public CA (Let's Encrypt) and forwards to the containers, while the container ports themselves are published on the loopback interface only (127.0.0.1: prefix on the host side of the ports: mapping) so nothing but the proxy can reach them. Django additionally needs SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https"), SECURE_SSL_REDIRECT, SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE and the public HTTPS origin in CSRF_TRUSTED_ORIGINS.

Usage

Backend (Django)

Run inside the backend container:

docker exec -it conduit_backend bash
python manage.py createsuperuser

Frontend (Angular)

The production build is embedded in an NGINX container and served at:

http://localhost:8282

Logging

All services log to stdout/stderr and are managed by Docker's json-file logging driver. Log rotation is enabled to prevent excessive disk usage.

Logs can be accessed via:

docker logs conduit_backend
docker logs conduit_frontend

Logs can optionally be persisted by redirecting Docker logs to a file.

docker logs conduit_backend > conduit_backend-logs.txt
docker logs conduit_frontend > conduit_frontend-logs.txt