Overview
The Wagtail Bakery Demo is designed for easy deployment to Heroku using container-based deployment with heroku.yml. This guide walks you through deploying the application to Heroku from scratch.
Prerequisites
Before deploying to Heroku, ensure you have:
Heroku Account
Create a free account at heroku.com if you don’t have one.
Heroku CLI
Install the Heroku CLI: macOS
Ubuntu/Debian
Windows
brew tap heroku/brew && brew install heroku
Verify installation:
Login to Heroku
Authenticate with your Heroku account:
Container Registry Login
Enable container deployment:
Quick Deploy
Deploy the Bakery Demo to Heroku in just a few commands:
# Clone the repository
git clone https://github.com/wagtail/bakerydemo.git
cd bakerydemo
# Create a Heroku app
heroku create your-app-name
# Add PostgreSQL database
heroku addons:create heroku-postgresql:essential-0
# Add Redis (optional but recommended)
heroku addons:create heroku-redis:mini
# Set required environment variables
heroku config:set DJANGO_SECRET_KEY= $( python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' )
heroku config:set DJANGO_SETTINGS_MODULE=bakerydemo.settings.production
# Deploy using container stack
heroku stack:set container
git push heroku main
# Open your app
heroku open
The first deployment may take 5-10 minutes as Heroku builds the Docker image and runs migrations.
Heroku Configuration Files
The project includes two configuration files for Heroku deployment:
heroku.yml
The heroku.yml file defines the container-based build and release process:
build :
docker :
web :
dockerfile : Dockerfile
config :
NIGHTLY : 0
release :
image : web
command :
- /venv/bin/python manage.py migrate --noinput
Configuration Breakdown:
build.docker.web : Specifies the Dockerfile to build the web container
build.config.NIGHTLY : Set to 0 for stable Wagtail, 1 for nightly builds
release.command : Runs database migrations automatically before each release
Procfile
The Procfile defines process types (legacy support):
release: yes "yes" | python manage.py migrate
web: uwsgi ./etc/uwsgi.ini
When using heroku.yml, the Procfile is primarily for reference. The heroku.yml configuration takes precedence.
Step-by-Step Deployment Guide
1. Create Your Heroku App
Create a new Heroku application:
# Create app with a specific name
heroku create bakery-demo-production
# Or let Heroku generate a name
heroku create
# Set stack to container
heroku stack:set container
2. Add Required Add-ons
PostgreSQL (Required)
Redis (Recommended)
Optional Add-ons
Add a PostgreSQL database: # Essential plan (suitable for production)
heroku addons:create heroku-postgresql:essential-0
# Or mini plan for small projects
heroku addons:create heroku-postgresql:mini
This automatically sets the DATABASE_URL environment variable. Add Redis for caching: # Mini plan (1MB cache)
heroku addons:create heroku-redis:mini
# Premium plans with persistence
heroku addons:create heroku-redis:premium-0
This automatically sets REDIS_URL and REDIS_TLS_URL environment variables. The production settings automatically use REDIS_TLS_URL when available for secure connections.
Papertrail (Logging) :heroku addons:create papertrail:chokin
Heroku Scheduler (Periodic Tasks) :heroku addons:create scheduler:standard
New Relic (Monitoring) :heroku addons:create newrelic:wayne
Set required environment variables:
# Generate and set Django secret key
heroku config:set DJANGO_SECRET_KEY= $( python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())' )
# Set Django settings module
heroku config:set DJANGO_SETTINGS_MODULE=bakerydemo.settings.production
# Set allowed hosts (replace with your domain)
heroku config:set DJANGO_ALLOWED_HOSTS=your-app-name.herokuapp.com
# Set primary host for admin emails
heroku config:set PRIMARY_HOST=your-app-name.herokuapp.com
# Ensure debug is off
heroku config:set DJANGO_DEBUG=off
Never commit your DJANGO_SECRET_KEY to version control. Always generate it securely and set it via environment variables.
4. Deploy Your Application
Push your code to Heroku:
# Deploy main branch
git push heroku main
# Or deploy a different branch
git push heroku your-branch:main
The deployment process:
Build Phase : Heroku builds the Docker image from the Dockerfile
Release Phase : Runs python manage.py migrate --noinput
Deploy Phase : Starts the web dyno with uWSGI
5. Post-Deployment Tasks
After deployment, complete these tasks:
Create Superuser
Create an admin user to access the Wagtail admin: heroku run python manage.py createsuperuser
Follow the prompts to set username, email, and password.
Load Demo Data (Optional)
Load the bakery demo content: heroku run python manage.py load_initial_data
Or enable automatic loading on deployment: heroku config:set DJANGO_LOAD_INITIAL_DATA=on
Verify Deployment
Open your application: Access the admin at: https://your-app-name.herokuapp.com/admin/
Advanced Configuration
Custom Domain Setup
Add a custom domain to your Heroku app:
Add Domain to Heroku
heroku domains:add www.yourdomain.com
heroku domains:add yourdomain.com
Get DNS Target
Note the DNS target provided by Heroku.
Update DNS Records
Add CNAME or ALIAS records with your DNS provider: www.yourdomain.com CNAME your-dns-target.herokudns.com
yourdomain.com ALIAS your-dns-target.herokudns.com
Enable Automatic SSL
Heroku automatically provisions SSL certificates:
Update Django Settings
Update allowed hosts: heroku config:set DJANGO_ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
heroku config:set PRIMARY_HOST=yourdomain.com
Configure AWS S3 for storing user uploads:
# Set AWS credentials
heroku config:set AWS_ACCESS_KEY_ID=your-access-key-id
heroku config:set AWS_SECRET_ACCESS_KEY=your-secret-access-key
heroku config:set AWS_STORAGE_BUCKET_NAME=your-bucket-name
heroku config:set AWS_S3_REGION_NAME=us-east-1
# Optional: Custom domain for S3
heroku config:set AWS_S3_CUSTOM_DOMAIN=cdn.yourdomain.com
Using S3 is highly recommended for production deployments to persist media files across dyno restarts.
Elasticsearch Search Backend
Add Elasticsearch for enhanced search:
# Using Bonsai Elasticsearch add-on
heroku addons:create bonsai:sandbox-10
# Get Elasticsearch URL
heroku config:get BONSAI_URL
# Set environment variables
heroku config:set ELASTICSEARCH_ENDPOINT=your-elasticsearch-host
heroku config:set ELASTICSEARCH_PORT= 9200
heroku config:set ELASTICSEARCH_USE_SSL=on
heroku config:set ELASTICSEARCH_VERIFY_CERTS=on
Cloudflare CDN Integration
Enable cache purging for Cloudflare:
heroku config:set FRONTEND_CACHE_CLOUDFLARE_ZONEID=your-zone-id
heroku config:set FRONTEND_CACHE_CLOUDFLARE_BEARER_TOKEN=your-api-token
Scaling Your Application
Dyno Scaling
Scale your web dynos based on traffic:
# Scale to 2 web dynos
heroku ps:scale web= 2
# Scale up to Standard-1X dyno type
heroku ps:type web=standard-1x
# View current dyno status
heroku ps
Dyno Types:
Type RAM Price Use Case Eco 512MB $5/mo Development/staging Basic 512MB $7/mo Low-traffic sites Standard-1X 512MB $25/mo Production sites Standard-2X 1GB $50/mo High-traffic sites Performance 2.5GB+ $250+/mo Enterprise applications
Database Scaling
Upgrade your PostgreSQL plan:
# View current plan
heroku pg:info
# Upgrade to Standard-0
heroku addons:upgrade heroku-postgresql:standard-0
# View database metrics
heroku pg:diagnose
Monitoring and Logs
View Application Logs
# Tail logs in real-time
heroku logs --tail
# View last 500 lines
heroku logs -n 500
# Filter by source
heroku logs --source app --tail
Application Metrics
View application metrics:
# View application metrics in browser
heroku open --metrics
# Or visit dashboard
heroku dashboard
Database Monitoring
# Database diagnostics
heroku pg:diagnose
# Connection info
heroku pg:info
# Long-running queries
heroku pg:ps
# Database backups
heroku pg:backups:capture
heroku pg:backups:download
Maintenance and Updates
Deploy Updates
# Pull latest changes
git pull origin main
# Deploy to Heroku
git push heroku main
# Monitor deployment
heroku logs --tail
Run Management Commands
# Access Django shell
heroku run python manage.py shell
# Run custom management commands
heroku run python manage.py update_index
# Create cache table
heroku run python manage.py createcachetable
Database Backups
# Create manual backup
heroku pg:backups:capture
# Schedule automatic backups (included in Standard plans and above)
heroku pg:backups:schedule DATABASE_URL --at '02:00 America/Los_Angeles'
# List backups
heroku pg:backups
# Download backup
heroku pg:backups:download
# Restore from backup
heroku pg:backups:restore b001 DATABASE_URL
Always test your backup restoration process in a staging environment before relying on it in production.
Troubleshooting
Error : “Application crashed” or “H10 error”Solutions :
Check application logs:
Verify environment variables:
Check dyno status:
Restart dynos:
Database Connection Issues
Error : “Could not connect to database”Solutions :
Verify DATABASE_URL is set:
heroku config:get DATABASE_URL
Check database status:
Run migrations:
heroku run python manage.py migrate
Error : 404 errors for CSS/JS filesSolutions :Static files are handled by WhiteNoise. Ensure:
WhiteNoise is in MIDDLEWARE (automatically configured in production.py)
Collectstatic runs during build (automatically handled in Dockerfile)
Manually collect static files: heroku run python manage.py collectstatic --noinput
Error : “Memory quota exceeded”Solutions :
Upgrade to larger dyno:
heroku ps:type web=standard-2x
Reduce worker threads in uwsgi.ini (edit locally and redeploy)
Monitor memory usage:
heroku logs --tail | grep "Memory"
Cost Optimization
Recommended Production Setup
Minimal Production (~$20/month):
# Eco dynos (can sleep)
heroku ps:type web=eco
heroku ps:scale web= 1
# Essential PostgreSQL
heroku addons:create heroku-postgresql:essential-0
# Mini Redis
heroku addons:create heroku-redis:mini
Standard Production (~$75/month):
# Standard dynos (no sleeping)
heroku ps:type web=standard-1x
heroku ps:scale web= 2
# Standard PostgreSQL
heroku addons:upgrade heroku-postgresql:standard-0
# Premium Redis with persistence
heroku addons:upgrade heroku-redis:premium-0
Eco dynos sleep after 30 minutes of inactivity. Use Basic or Standard dynos for production sites that need 24/7 availability.
Next Steps
Production Settings Deep dive into production configuration
Docker Deployment Alternative deployment with Docker
Environment Variables Learn about configuration options
Deployment Overview Explore other deployment options