Django + Vue Notes App¶
A full-stack notes application built with Django and Vue.js, running as a single container with PostgreSQL database integration. This example demonstrates how AppMecca handles database provisioning, credential injection, and migration management.
Source: git@gitlab.com:appmecca-sample-apps/django-vue-notes.git
What This App Demonstrates¶
- Database integration --
database: enabled: trueauto-provisions PostgreSQL credentials - Django migrations via entrypoint scripts
- The
APPMECCA_SERVICEenv var -- guards migrations so only thewebservice runs them - Database backups and restores via the CLI
- Trailing-slash health checks -- Django's
APPEND_SLASHsetting means the health check path is/health/(not/health)
appmecca.yaml¶
containers:
- name: web
dockerfile: Dockerfile
context: .
deploy:
- name: web
container: web
port: 8000
health_check:
path: /health/
database:
enabled: true
The only addition compared to a simple web app is the database section. When enabled: true, AppMecca:
- Creates a dedicated PostgreSQL database for this app and branch on the managed database server
- Generates a secure password and keeps it in the platform secret store
- Injects
DATABASE_URL,DB_HOST,DB_PORT,DB_NAME,DB_USER, andDB_PASSWORDinto every container
The database and user names are generated identifiers (something like am_a1b2c3_db), not
django-vue-notes_db — always read them from the environment.
Trailing slash on Django health checks
Django's APPEND_SLASH setting redirects /health to /health/ with a 301. The platform health check follows redirects, but this adds latency. Set the health check path to /health/ (with the trailing slash) to avoid the redirect entirely.
How Migrations Work¶
AppMecca does not run migrations for you. Instead, your container's entrypoint script handles them on every deployment.
entrypoint.sh¶
#!/bin/bash
set -e
echo "==> Waiting for database..."
RETRIES=10
DELAY=3
for i in $(seq 1 $RETRIES); do
python -c "
import psycopg2
import os
try:
conn = psycopg2.connect(
host=os.environ.get('DB_HOST', 'localhost'),
port=os.environ.get('DB_PORT', '5432'),
dbname=os.environ.get('DB_NAME', 'app'),
user=os.environ.get('DB_USER', 'app'),
password=os.environ.get('DB_PASSWORD', ''),
)
conn.close()
print('Database is ready.')
except Exception as e:
print(f'Database not ready: {e}')
exit(1)
" && break
echo " Attempt $i/$RETRIES failed. Retrying in ${DELAY}s..."
sleep $DELAY
done
# Only the web service runs migrations
if [ "$APPMECCA_SERVICE" = "web" ]; then
echo "==> Running migrations..."
python manage.py migrate --noinput
fi
echo "==> Starting gunicorn..."
exec gunicorn config.wsgi:application \
--bind 0.0.0.0:8000 \
--workers 2 \
--timeout 120 \
--access-logfile - \
--error-logfile -
The script does three things:
- Waits for the database -- it may take a few seconds to become reachable after your container starts. The retry loop prevents crash-on-first-deploy.
- Guards migrations with
APPMECCA_SERVICE-- AppMecca sets this variable automatically to the service name from yourappmecca.yaml. If you later add a worker service, only thewebservice will run migrations. - Starts the application with
exec-- Replaces the shell process so that Docker signals (SIGTERM) reach gunicorn directly for graceful shutdown.
The APPMECCA_SERVICE variable
AppMecca injects APPMECCA_SERVICE into every container with the service name from the deploy section. For this app, the web container gets APPMECCA_SERVICE=web. This is useful when multiple services share the same image and you need to conditionally run setup steps like migrations.
Django settings¶
Configure Django to read credentials from the injected environment variables:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"HOST": os.environ.get("DB_HOST", "localhost"),
"PORT": os.environ.get("DB_PORT", "5432"),
"NAME": os.environ.get("DB_NAME", "app"),
"USER": os.environ.get("DB_USER", "app"),
"PASSWORD": os.environ.get("DB_PASSWORD", ""),
}
}
Or use DATABASE_URL with dj-database-url for a one-liner:
import dj_database_url
DATABASES = {
"default": dj_database_url.config(default=os.environ.get("DATABASE_URL"))
}
Deploy It¶
# Register the app
mecca register git@gitlab.com:appmecca-sample-apps/django-vue-notes.git -e dev
# Build the Docker image
mecca build trigger -e dev -g git@gitlab.com:appmecca-sample-apps/django-vue-notes.git
# Deploy
mecca app deploy -e dev django-vue-notes
Expected output
Your app is live at https://django-vue-notes-web.dev.appmecca.net. The service name is always
part of the hostname, even for a single-service app — run mecca app show django-vue-notes -e dev
to see the exact URL for your group.
Managing the Database¶
Once deployed, use the app-level backup commands to create backups and restore from them. A backup is a bundle — the database plus any declared drives, with a manifest — so a restore brings back a consistent set rather than a lone SQL file.
Create a backup¶
Expected output
List backups¶
Expected output
Restore from a backup¶
mecca app restore django-vue-notes \
backups/dev/django-vue-notes/main/manual/2026-06-15T10-23-45Z/ --force -e dev
The second argument is a bundle prefix (a directory), not a path to a .sql.gz file. Copy
it from the mecca app backups output.
Restore replaces all data
The --force flag skips the confirmation prompt. A restore replaces the entire database with the bundle contents. Always create a fresh backup before restoring if you need to preserve current data.
Loading a dump from elsewhere
To restore a pg_dump you produced outside AppMecca, use
the dashboard's Database tab (open the app, choose the file, confirm). A custom-format dump
(pg_dump -Fc) is strongly preferred.
See Database Operations for the full command reference.
Key Takeaways¶
- Add
database: enabled: trueto yourappmecca.yaml-- that is all the AppMecca-specific configuration needed - AppMecca injects
DATABASE_URL,DB_HOST,DB_PORT,DB_NAME,DB_USER, andDB_PASSWORDautomatically - The database and user names are generated — read them from the environment, never construct them
- Use an entrypoint script that waits for the database, runs migrations, then starts your app
- Guard migrations with
APPMECCA_SERVICEto prevent duplicate runs when you add workers later - Back up your app before deploying schema changes
What's Next?¶
- FastAPI Todos -- Another database app using FastAPI and SQLAlchemy
- Django Celery Tasks -- Add background workers to a Django app
- Database Configuration -- Full reference for database settings
- Database Operations -- Backups, restores, and management