Skip to content

Instantly share code, notes, and snippets.

@yeiichi
Created November 9, 2025 01:04
Show Gist options
  • Select an option

  • Save yeiichi/cf1760c2e8b0ec2e3f36cb4048620e7f to your computer and use it in GitHub Desktop.

Select an option

Save yeiichi/cf1760c2e8b0ec2e3f36cb4048620e7f to your computer and use it in GitHub Desktop.
Helper Makefile for Django + Docker Compose development
# language: Makefile
# ==============================================================================
# Makefile.django-docker-helper
# ------------------------------------------------------------------------------
# Helper Makefile for Django + Docker Compose development.
#
# PURPOSE:
# - Simplify common Django and Docker workflows.
# - Provide short aliases for build, run, migrate, backup, test, and more.
# - Encourage consistent developer operations across environments.
#
# USAGE:
# make <target>
# e.g. make up, make migrate, make logs, make backup
#
# HIGHLIGHTS:
# • Portable — works with any Django project using docker-compose (services: web, db)
# • Safe — no destructive operations unless explicitly called (see `make reset`)
# • Developer-side only — not used in production
#
# EXAMPLES:
# $ make up # Start containers
# $ make migrate # Apply migrations
# $ make superuser # Create admin user
# $ make backup # Dump database to ./backup.sql
# $ make fmt # Auto-format code (ruff + black)
#
# AUTHOR: Eiichi YAMAMOTO
# LICENSE: MIT License
# VERSION: 2025.11
# URL: https://yeiichi.com
# ==============================================================================
# ---- Config ----
DC ?= docker compose
WEB ?= web
DB ?= db
MANAGE ?= python manage.py
DB_USER ?= appuser
DB_NAME ?= appdb
DB_HOST ?= db
DB_PORT ?= 5432
# ---- Help (default) ----
.DEFAULT_GOAL := help
.PHONY: help
help: ## Show this help
@awk 'BEGIN{FS":.*##"; printf "\nUsage: make <target>\n\nTargets:\n"} /^[a-zA-Z0-9_%-]+:.*?##/{printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
# ---- Lifecycle ----
.PHONY: up
up: ## Start containers (detached)
$(DC) up -d
.PHONY: down
down: ## Stop and remove containers (keep volume)
$(DC) down
.PHONY: reset
reset: ## Stop and remove everything (including DB volume)
$(DC) down -v --remove-orphans
.PHONY: rebuild
rebuild: ## Rebuild web image and restart
$(DC) build --pull --no-cache $(WEB)
$(DC) up -d --no-deps $(WEB)
.PHONY: logs
logs: ## Tail logs (all services)
$(DC) logs -f --tail=200
# ---- Django shortcuts ----
.PHONY: migrate
migrate: ## Run Django migrations
$(DC) exec $(WEB) $(MANAGE) migrate
.PHONY: makemigrations
makemigrations: ## Make migrations
$(DC) exec $(WEB) $(MANAGE) makemigrations
.PHONY: superuser
superuser: ## Create Django superuser
$(DC) exec $(WEB) $(MANAGE) createsuperuser
.PHONY: shell
shell: ## Open Django shell
$(DC) exec $(WEB) $(MANAGE) shell
.PHONY: run
run: ## Run dev server on :8000
$(DC) exec $(WEB) $(MANAGE) runserver 0.0.0.0:8000
.PHONY: collectstatic
collectstatic: ## Collect static files (non-interactive)
$(DC) exec $(WEB) $(MANAGE) collectstatic --noinput
.PHONY: check
check: ## Django system checks
$(DC) exec $(WEB) $(MANAGE) check --deploy
# ---- Testing & linting (optional tools) ----
.PHONY: test
test: ## Run tests
$(DC) exec $(WEB) pytest -q
.PHONY: fmt
fmt: ## Format code (ruff/black if installed)
$(DC) exec $(WEB) ruff check --fix .
$(DC) exec $(WEB) black .
.PHONY: lint
lint: ## Lint only
$(DC) exec $(WEB) ruff check .
$(DC) exec $(WEB) black --check .
# ---- Database ops ----
.PHONY: psql
psql: ## Open psql in the DB container
$(DC) exec -e PGPASSWORD=$$( $(DC) exec -T $(DB) printenv POSTGRES_PASSWORD ) \
$(DB) psql -U $(DB_USER) -d $(DB_NAME)
.PHONY: dbshell
dbshell: ## Django dbshell (uses DATABASE_URL)
$(DC) exec $(WEB) $(MANAGE) dbshell
.PHONY: dump
dump: ## Dump a named app (APP=your_app) to fixtures/APP.json
@test -n "$(APP)" || (echo "Usage: make dump APP=your_app"; exit 2)
$(DC) exec $(WEB) $(MANAGE) dumpdata $(APP) --indent 2 > fixtures/$(APP).json
.PHONY: load
load: ## Load a fixture (FILE=fixtures/foo.json)
@test -n "$(FILE)" || (echo "Usage: make load FILE=fixtures/foo.json"; exit 2)
$(DC) exec -T $(WEB) $(MANAGE) loaddata $(FILE)
.PHONY: backup
backup: ## pg_dump to ./backup.sql
$(DC) exec $(DB) pg_dump -U $(DB_USER) -d $(DB_NAME) > backup.sql
@echo "Wrote ./backup.sql"
.PHONY: restore
restore: ## psql < backup.sql (requires ./backup.sql)
@test -f backup.sql || (echo "backup.sql not found"; exit 2)
$(DC) exec -T $(DB) psql -U $(DB_USER) -d $(DB_NAME) < backup.sql
# ---- Utilities ----
.PHONY: sh
sh: ## Shell into web container
$(DC) exec $(WEB) sh -lc 'exec $$SHELL -l || sh'
.PHONY: dbsh
dbsh: ## Shell into db container
$(DC) exec $(DB) sh -lc 'exec $$SHELL -l || sh'
.PHONY: health
health: ## Show container health/status
$(DC) ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment