Skip to main content

Conduit Container

This repository contains the deployment configuration for the Conduit full-stack application, a Medium.com clone. The setup uses Docker and Docker Compose to orchestrate a complete production environment.


Table of Contents

  1. Description
  2. Prerequisites
  3. Quickstart
  4. Usage

Description

Components

  • Frontend: Angular Single Page Application (SPA) served with Node.js serve package
  • Backend: Django REST API running with Gunicorn WSGI server
  • Database: PostgreSQL for data persistence

Purpose

This is a containerized deployment using multi-stage Docker builds to minimize image sizes while maintaining production-ready configuration. All services are orchestrated via Docker Compose with proper volume management for data persistence and automatic restart policies.


Prerequisites

  • Docker: Version 20.10 or higher
  • Docker Compose: Version 2.0 or higher
  • Git: For repository management

Verify installations:

docker --version
docker compose version
git --version

Quickstart

1. Clone the repository

git clone git clone -b feature/conduit-container git@github.com:Ozinho78/conduit-deployment.git
cd conduit-deployment

2. Create environment file

cp .env.example .env

3. Configure environment variables

Edit .env and set required values:

# REQUIRED: Set secure password
POSTGRES_PASSWORD=your_secure_password_here

# REQUIRED: Generate Django secret key
DJANGO_SECRET_KEY=your_generated_secret_key_here

# REQUIRED: Add your VM IP address
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1,backend,<YOUR_VM_IP_HERE>
CORS_ALLOWED_ORIGINS=http://localhost:8282,http://<YOUR_VM_IP_HERE>:8282

Generate Django Secret Key:

python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'

4. Build and start services

docker compose up -d --build

5. Access application

  • Frontend: http://<YOUR_VM_IP:8282>
  • Backend API: http://<YOUR_VM_IP>:8000/api
  • Backend Admin: http://<YOUR_VM_IP>:8000/admin

Usage

Initial Setup

Directory structure after setup:

conduit-deployment/
├── .dockerignore # Excludes Python cache, venv, .git, node_modules, dist from Docker context
├── docker-compose.yaml # Orchestration: frontend, backend, postgres services
├── .env.example # Template for .env, contains environment variables
├── .env # Runtime environment variables (NOT in Git!), created by YOU
├── .gitignore # Excludes .env, logs, IDE configs, OS files
├── README.md # This document, project documentation with ToC, quickstart, usage
├── conduit-frontend/ # contains frontend code, coded with Angular
│ └── frontend.Dockerfile # Multi-stage build: Angular build + npm serve
├── conduit-backend/ # Contains backend code, coded with Django
│ └── backend.Dockerfile # Multi-stage build: Django app + Gunicorn WSGI
│ └── entrypoint.sh # Defines and controls default commands when container starts
│ └── conduit/
│ └── settings.py # Must be modified for production (ALLOWED_HOSTS, DB config)

Environment Configuration

The .env file contains all configuration for the deployment. This file is not stored in Git for security reasons.

Create from template:

cp .env.example .env
nano .env # or use your preferred editor

Critical settings to modify:

  1. Database Password (REQUIRED):

    POSTGRES_PASSWORD=use_a_strong_random_password
  2. Django Secret Key (REQUIRED): Generate using Python:

    python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'

    Then set in .env:

    DJANGO_SECRET_KEY=<your_generated_key_here>
  3. Allowed Hosts (REQUIRED for production): Replace YOUR_VM_IP_HERE with your actual VM IP address:

    DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1,backend,<YOUR_VM_IP_HERE>
    CORS_ALLOWED_ORIGINS=http://localhost:8282,http://<YOUR_VM_IP_HERE>:8282

Optional settings:

  • DEBUG: Set to True only for development (default: False)
  • POSTGRES_DB: Database name (default: conduit)
  • POSTGRES_USER: Database user (default: conduit)
  • FRONTEND_PORT: External port for frontend (default: 8282)
  • BACKEND_PORT: External port for backend (default: 8000)

Building and Running

First-time build:

docker compose up -d --build

Start existing containers:

docker compose up -d

Rebuild after code changes:

docker compose up -d --build

Check service status:

docker compose ps

Expected output:

NAME                IMAGE                      STATUS
conduit-backend conduit-deployment-backend Up
conduit-database postgres:13-alpine Up
conduit-frontend conduit-deployment-frontend Up

Accessing the Application

Once services are running, access the application at:

ServiceURLDescription
Frontendhttp://<YOUR_VM_IP>:8282Angular SPA
Backend APIhttp://<YOUR_VM_IP>:8000/apiREST API endpoints
Admin Panelhttp://<YOUR_VM_IP>:8000/adminDjango admin interface

Create superuser for admin access:

docker compose exec backend python manage.py createsuperuser

Managing Services

Stop services (keeps data):

docker compose stop

Start stopped services:

docker compose start

Restart all services:

docker compose restart

Restart specific service:

docker compose restart backend
docker compose restart frontend
docker compose restart database

Stop and remove containers (keeps volumes):

docker compose down

Stop and remove everything including data:

⚠️ WARNING This deletes all database data!

docker compose down -v

Working with Logs

View all logs:

docker compose logs

Follow logs in real-time:

docker compose logs -f

View logs for specific service:

docker compose logs backend
docker compose logs frontend
docker compose logs database

Follow specific service logs:

docker compose logs -f backend

Save logs to file:

# Save backend logs
docker logs conduit-backend > backend-logs.txt

# Save frontend logs
docker logs conduit-frontend > frontend-logs.txt

# Save database logs
docker logs conduit-database > database-logs.txt

# Save all logs with timestamps
docker compose logs --timestamps > all-logs.txt

View last N lines:

docker compose logs --tail=100 backend

Project Information

  • Last Updated: January 2026
  • Course: DevSecOps
  • Project: Conduit Containerization