This repository contains a Docker-based deployment configuration for Apache Airflow designed to run on Aiven's App Runtime platform.
Apache Airflow is a platform to programmatically author, schedule, and monitor workflows. This project provides a containerized setup that:
- Extends the official Apache Airflow Docker image
- Runs webserver, scheduler, and triggerer in a single container (
airflow standalone) - Uses LocalExecutor (no Redis/Celery required)
- Automatically runs database migrations on startup
- Configures the application for Aiven App Runtime deployment
- Aiven account with App Runtime access
- PostgreSQL database service in Aiven (for Airflow's metadata storage)
- Git repository access (this repo)
Airflow standalone runs webserver, scheduler, triggerer, DAG processor, and API server in one container. Recommended compute:
| Resource | Minimum | Recommended |
|---|---|---|
| RAM | 2 GB | 4–8 GB |
| CPU | 1 vCPU | 2 vCPUs |
Startup can take 5–7 minutes with limited resources. If the app is slow to become ready or returns Bad Gateway, increase RAM to at least 4 GB. The official Docker guide recommends 4 GB minimum, 8 GB for smoother operation.
A database connection must be configured. You can use either:
When you connect a PostgreSQL service in Aiven App Runtime's "Connect services" step, Aiven automatically injects DATABASE_URL. The entrypoint detects this and configures Airflow accordingly—no extra setup needed.
AIRFLOW__DATABASE__SQL_ALCHEMY_CONN- PostgreSQL connection string for Airflow metadata
Example format:
postgresql+psycopg2://username:password@hostname:port/database
Get the connection string from your Aiven PostgreSQL service. Ensure the database user has sufficient permissions to create tables and run migrations.
Important: Aiven rejects environment variable keys that start with _. Do not use _AIRFLOW_DB_MIGRATE, _AIRFLOW_WWW_USER_CREATE, or _AIRFLOW_WWW_USER_PASSWORD—they will cause validation errors.
For the first deployment, you may want to create an admin user. Use these Aiven-compatible names:
AIRFLOW_WWW_USER_CREATE- Set totrueto create an admin userAIRFLOW_WWW_USER_PASSWORD- Admin password (required when creating user)
Migrations run automatically on startup (no variable needed). To disable, set AIRFLOW_DB_MIGRATE=false.
Note: Airflow 3.x standalone mode auto-creates an admin user with a random password on first run. Check the application logs for Password for user 'admin': <password>—you may not need to set these variables.
Example for first run:
AIRFLOW_WWW_USER_CREATE=true
AIRFLOW_WWW_USER_PASSWORD=your-secure-password
AIRFLOW_UID- User ID for file permissions (default: 50000)PORT- If Aiven injects aPORTenvironment variable, the webserver will automatically listen on it
-
Create a PostgreSQL Service in Aiven (if you don't have one)
- This will store Airflow's metadata (DAGs, task history, connections, etc.)
-
Create an App Runtime Application
- Source: Point to this GitHub repository (
https://github.com/StanDmitrievAiven/airflow.git) - Branch:
main
- Source: Point to this GitHub repository (
-
Configure Environment Variables
- Add
AIRFLOW__DATABASE__SQL_ALCHEMY_CONNwith your PostgreSQL connection string from Aiven - For first run, add
AIRFLOW_WWW_USER_CREATE=trueandAIRFLOW_WWW_USER_PASSWORD=<password>
- Add
-
Configure Port
- Open port 8080 in your App Runtime configuration (or the port Aiven assigns via
PORTenv var) - Airflow's web UI will be accessible on this port
- Open port 8080 in your App Runtime configuration (or the port Aiven assigns via
-
Deploy
- Aiven will automatically build and deploy your application
- Check the logs to verify successful startup and migration
Once deployed, access the Airflow web UI at:
https://<your-app-hostname>:8080/
Or, if Aiven uses a different port via the PORT environment variable:
https://<your-app-hostname>:<PORT>/
Default login (if you created a user): admin / your configured password.
.
├── Dockerfile # Extends official Airflow image
├── entrypoint.sh # Startup script: validates env, runs migrations, starts Airflow
├── dags/ # Add your DAG files here (embedded in image)
├── .gitattributes # Git configuration for line endings
└── README.md # This file
-
Build: Extends
apache/airflow:3.1.8with:- LocalExecutor configuration (no Redis needed)
- Custom entrypoint for validation and migrations
- DAGs from the
dags/directory
-
Runtime: The entrypoint script:
- Validates that
AIRFLOW__DATABASE__SQL_ALCHEMY_CONNis set - Runs database migrations automatically
- Starts Airflow in standalone mode (webserver + scheduler + triggerer in one process)
- Validates that
Add your DAG files to the dags/ directory in this repository. They will be copied into the image at build time. After pushing changes, trigger a new deployment in Aiven to pick up the new DAGs.
To use a different Airflow image version, set the build argument:
ARG AIRFLOW_IMAGE=apache/airflow:3.0.0To add Airflow providers (e.g. for PostgreSQL, HTTP, etc.), create a requirements.txt:
apache-airflow-providers-postgres
apache-airflow-providers-http
Then add to the Dockerfile before the CMD:
COPY requirements.txt /requirements.txt
RUN pip install --no-cache-dir -r /requirements.txt- Stateless: Logs are ephemeral. For persistent logs, configure external logging (e.g. Aiven for OpenSearch).
- LocalExecutor only: No Celery worker support. For parallel task execution, use a Kubernetes deployment instead.
- Single instance: Suitable for development and moderate workloads. For high availability, use the Airflow Helm Chart on Kubernetes.
-
Wait for startup – Airflow standalone can take 3–5 minutes to fully start. The container may show "Running" before the webserver is ready. Wait a few minutes and try again.
-
Check application logs – In Aiven, open the application logs and look for:
Running on http://0.0.0.0:8080(webserver started successfully)- Database connection errors
- Python tracebacks or migration failures
-
Try the root URL – Use
https://<your-app-url>/(without/login). Airflow may redirect you to the login page. -
Verify port – Ensure the internal port in Aiven matches 8080 (Airflow's default). If Aiven injects a
PORTenv var, the entrypoint uses it automatically.
- Verify your PostgreSQL connection string is correct
- Ensure the database is accessible from App Runtime (check VPC/network configuration)
- Check that the database user has necessary permissions (CREATE, ALTER, etc.)
- Check the application logs for specific migration errors
- Ensure the database is empty or compatible with Airflow's schema
- Verify the connection string uses
postgresql+psycopg2://(notpostgresql://)
- Ensure port 8080 (or
PORTif set) is opened in your App Runtime configuration - If Aiven injects a
PORTvariable, the entrypoint automatically configures Airflow to use it
- Use a strong password for
AIRFLOW_WWW_USER_PASSWORD - Consider configuring Airflow authentication (OAuth, LDAP, etc.) for production
- Restrict network access to the application as appropriate
- Do not commit secrets to the repository; use Aiven's environment variable configuration
This deployment configuration is provided as-is. Apache Airflow is licensed under the Apache License 2.0.