Dockerize Django app with dev/beta/prod env config and uv.
CI / test (pull_request) Successful in 7s

Replace hardcoded settings with environment-driven config, add Docker
compose for local and production deploys, migrate from pip to uv, and
split Gitea workflows so PRs run tests only while master pushes deploy.
This commit is contained in:
2026-07-02 06:19:45 -05:00
parent c8574d76d4
commit b5275f1b7e
22 changed files with 1124 additions and 201 deletions
+54 -12
View File
@@ -2,10 +2,9 @@
set -euo pipefail
REPO_ROOT="/home/westfarn/Documents/django_live_sites/Company_Site"
APP_DIR="$REPO_ROOT/company_site"
VENV="$REPO_ROOT/venv"
SETTINGS="$APP_DIR/company_site/settings.py"
LOCAL_SETTINGS="$APP_DIR/company_site/local_settings.py"
ENV_FILE="$REPO_ROOT/.env"
COMPOSE_FILE="$REPO_ROOT/docker-compose.prod.yml"
VALIDATE_SCRIPT="$REPO_ROOT/scripts/validate-env.sh"
if [[ $# -lt 1 || -z "${1:-}" ]]; then
echo "Usage: $0 <checkout-directory>" >&2
@@ -13,24 +12,67 @@ if [[ $# -lt 1 || -z "${1:-}" ]]; then
fi
CHECKOUT="$1"
DEPLOY_MODE="${DEPLOY_MODE:-docker}"
cp "$SETTINGS" /tmp/company_site_settings.py.bak
if [[ "$DEPLOY_MODE" == "docker" ]]; then
echo "Syncing application files to $REPO_ROOT (preserving server .env)..."
rsync -a --delete \
--exclude .git/ \
--exclude .venv/ \
--exclude .env \
--exclude db.sqlite3 \
--exclude staticfiles/ \
"$CHECKOUT/" "$REPO_ROOT/"
if [[ ! -f "$ENV_FILE" ]]; then
echo "Missing $ENV_FILE on the server." >&2
echo "Create it from .env.prod.example and configure production values." >&2
exit 1
fi
bash "$VALIDATE_SCRIPT" "$ENV_FILE"
cd "$REPO_ROOT"
echo "Building Docker images..."
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" build
echo "Starting containers..."
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d --remove-orphans
echo "Running database migrations..."
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" exec -T web \
uv run python manage.py migrate --noinput
echo "Deploy complete."
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" ps
exit 0
fi
# Legacy venv/systemd deploy (DEPLOY_MODE=legacy)
APP_DIR="$REPO_ROOT/company_site"
VENV="$REPO_ROOT/.venv"
SETTINGS_DIR="$APP_DIR/company_site/settings"
LOCAL_SETTINGS="$APP_DIR/company_site/local_settings.py"
cp -r "$SETTINGS_DIR" /tmp/company_site_settings.bak
cp "$LOCAL_SETTINGS" /tmp/company_site_local_settings.py.bak 2>/dev/null || true
rsync -a --delete \
--exclude venv/ \
--exclude .venv/ \
--exclude .git/ \
--exclude 'company_site/company_site/settings.py' \
--exclude .env \
--exclude 'company_site/company_site/settings/' \
--exclude 'company_site/company_site/local_settings.py' \
"$CHECKOUT/" "$REPO_ROOT/"
cp /tmp/company_site_settings.py.bak "$SETTINGS"
rm -rf "$SETTINGS_DIR"
cp -r /tmp/company_site_settings.bak "$SETTINGS_DIR"
cp /tmp/company_site_local_settings.py.bak "$LOCAL_SETTINGS" 2>/dev/null || true
source "$VENV/bin/activate"
pip install -r "$REPO_ROOT/requirements.txt"
uv sync --frozen --directory "$REPO_ROOT"
cd "$APP_DIR"
python manage.py migrate --noinput
python manage.py collectstatic --noinput
uv run python manage.py migrate --noinput
uv run python manage.py collectstatic --noinput
sudo systemctl restart company
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
set -euo pipefail
cd /app/company_site
wait_for_database() {
if [[ -z "${DATABASE_URL:-}" && -z "${DB_HOST:-}" ]]; then
return 0
fi
echo "Waiting for database..."
for _ in $(seq 1 30); do
if uv run python - <<'PY'
import os
import sys
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "company_site.settings")
import django
from django.db import connections
from django.db.utils import OperationalError
django.setup()
try:
connections["default"].ensure_connection()
except OperationalError:
sys.exit(1)
PY
then
echo "Database is ready."
return 0
fi
sleep 2
done
echo "Database did not become ready in time." >&2
exit 1
}
wait_for_database
uv run python manage.py migrate --noinput
uv run python manage.py collectstatic --noinput
exec uv run gunicorn company_site.wsgi:application \
--bind "${GUNICORN_BIND:-0.0.0.0:8000}" \
--workers "${GUNICORN_WORKERS:-2}"
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
set -euo pipefail
ENV_FILE="${1:?Usage: $0 <env-file>}"
if [[ ! -f "$ENV_FILE" ]]; then
echo "Environment file not found: $ENV_FILE" >&2
exit 1
fi
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
DJANGO_ENV="${DJANGO_ENV:-prod}"
required_vars=(
DJANGO_SECRET_KEY
DJANGO_ALLOWED_HOSTS
DB_PASSWORD
DB_NAME
DB_USER
DATABASE_URL
)
if [[ "$DJANGO_ENV" == "prod" || "$DJANGO_ENV" == "beta" ]]; then
required_vars+=(
RECAPTCHA_PUBLIC_KEY
RECAPTCHA_PRIVATE_KEY
EMAIL_HOST_USER
EMAIL_HOST_PASSWORD
)
fi
if [[ "$DJANGO_ENV" == "prod" ]]; then
required_vars+=(TIANJI_WEBSITE_ID)
fi
missing=()
for var in "${required_vars[@]}"; do
if [[ -z "${!var:-}" ]]; then
missing+=("$var")
fi
done
if ((${#missing[@]} > 0)); then
echo "Missing required environment variables in $ENV_FILE:" >&2
printf ' - %s\n' "${missing[@]}" >&2
echo "Copy .env.prod.example to .env on the server and set production values." >&2
exit 1
fi
if [[ "$DJANGO_ENV" == "prod" && "$DJANGO_SECRET_KEY" == change-me* ]]; then
echo "DJANGO_SECRET_KEY must be changed from the example value for production." >&2
exit 1
fi
echo "Environment validation passed (DJANGO_ENV=$DJANGO_ENV)."