Repository navigation
Description
Description
In order to use the production image we are already working on a helm chart, but we might want to add a production-ready docker compose that will be able to run airflow installation.
Use case / motivation
For local tests/small deployments - being able to have such docker-compose environment would be really nice.
We seem to get to consensus that we need to have several docker-compose "sets" of files:
- Local Executor
- Celery Executor
- Kubernetes Executor (??? do we need to have a Kubernetes Executor in a Compose ? I guess not...)
They should be varianted and possible to specify the number of parameters:
- Database (Postgres/MySQL)
- Redis vs. Rabitmq (should we choose one ???)
- Ports
- Volumes (persistent / not)
- Airflow Images
- Fernet Key
- RBAC
Depending on the setup, those Docker compose file should do proper DB initialisation.
Example Docker Compose (From https://apache-airflow.slack.com/archives/CQAMHKWSJ/p1587748008106000) that we might use as a base and #8548 . This is just example so this issue will not implement all of it and we will likely split those docker-compose into separate postgres/sqlite/mysql similarly as we do in CI script, so I wanted to keep it as separate issue - we will deal with user creation in #8606
version: '3'
services:
postgres:
image: postgres:latest
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=airflow
- POSTGRES_PORT=5432
ports:
- 5432:5432
redis:
image: redis:latest
ports:
- 6379:6379
flower:
image: apache/airflow:1.10.10
volumes:
- ./airflow-data/dags:/opt/airflow/dags
environment:
- AIRFLOW__CORE__EXECUTOR=CeleryExecutor
- AIRFLOW__CELERY__BROKER_URL=redis://:@redis:6379/0
- AIRFLOW__CELERY__RESULT_BACKEND=db+postgresql://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__SQL_ALCHEMY_CONN=postgresql+psycopg2://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__FERNET_KEY=FB0o_zt4e3Ziq3LdUUO7F2Z95cvFFx16hU8jTeR1ASM=
- AIRFLOW__CORE__LOAD_EXAMPLES=False
- AIRFLOW__WEBSERVER__RBAC=True
command: flower
ports:
- 5555:5555
airflow:
image: apache/airflow:1.10.10
environment:
- AIRFLOW__CORE__EXECUTOR=CeleryExecutor
- AIRFLOW__CELERY__BROKER_URL=redis://:@redis:6379/0
- AIRFLOW__CELERY__RESULT_BACKEND=db+postgresql://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__SQL_ALCHEMY_CONN=postgresql+psycopg2://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__FERNET_KEY=FB0o_zt4e3Ziq3LdUUO7F2Z95cvFFx16hU8jTeR1ASM=
- AIRFLOW__CORE__LOAD_EXAMPLES=False
- AIRFLOW__WEBSERVER__RBAC=True
command: webserver
ports:
- 8080:8080
volumes:
- ./airflow-data/dags:/opt/airflow/dags
- ./airflow-data/logs:/opt/airflow/logs
- ./airflow-data/plugins:/opt/airflow/plugins
airflow-scheduler:
image: apache/airflow:1.10.10
container_name: airflow_scheduler_cont
environment:
- AIRFLOW__CORE__EXECUTOR=CeleryExecutor
- AIRFLOW__CELERY__BROKER_URL=redis://:@redis:6379/0
- AIRFLOW__CELERY__RESULT_BACKEND=db+postgresql://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__SQL_ALCHEMY_CONN=postgresql+psycopg2://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__FERNET_KEY=FB0o_zt4e3Ziq3LdUUO7F2Z95cvFFx16hU8jTeR1ASM=
- AIRFLOW__CORE__LOAD_EXAMPLES=False
- AIRFLOW__WEBSERVER__RBAC=True
command: scheduler
volumes:
- ./airflow-data/dags:/opt/airflow/dags
- ./airflow-data/logs:/opt/airflow/logs
- ./airflow-data/plugins:/opt/airflow/plugins
airflow-worker1:
image: apache/airflow:1.10.10
container_name: airflow_worker1_cont
environment:
- AIRFLOW__CORE__EXECUTOR=CeleryExecutor
- AIRFLOW__CELERY__BROKER_URL=redis://:@redis:6379/0
- AIRFLOW__CELERY__RESULT_BACKEND=db+postgresql://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__SQL_ALCHEMY_CONN=postgresql+psycopg2://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__FERNET_KEY=FB0o_zt4e3Ziq3LdUUO7F2Z95cvFFx16hU8jTeR1ASM=
- AIRFLOW__CORE__LOAD_EXAMPLES=False
- AIRFLOW__WEBSERVER__RBAC=True
command: worker
volumes:
- ./airflow-data/dags:/opt/airflow/dags
- ./airflow-data/logs:/opt/airflow/logs
- ./airflow-data/plugins:/opt/airflow/plugins
airflow-worker2:
image: apache/airflow:1.10.10
container_name: airflow_worker2_cont
environment:
- AIRFLOW__CORE__EXECUTOR=CeleryExecutor
- AIRFLOW__CELERY__BROKER_URL=redis://:@redis:6379/0
- AIRFLOW__CELERY__RESULT_BACKEND=db+postgresql://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__SQL_ALCHEMY_CONN=postgresql+psycopg2://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__FERNET_KEY=FB0o_zt4e3Ziq3LdUUO7F2Z95cvFFx16hU8jTeR1ASM=
- AIRFLOW__CORE__LOAD_EXAMPLES=False
- AIRFLOW__WEBSERVER__RBAC=True
command: worker
volumes:
- ./airflow-data/dags:/opt/airflow/dags
- ./airflow-data/logs:/opt/airflow/logs
- ./airflow-data/plugins:/opt/airflow/plugins
airflow-worker3:
image: apache/airflow:1.10.10
container_name: airflow_worker3_cont
environment:
- AIRFLOW__CORE__EXECUTOR=CeleryExecutor
- AIRFLOW__CELERY__BROKER_URL=redis://:@redis:6379/0
- AIRFLOW__CELERY__RESULT_BACKEND=db+postgresql://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__SQL_ALCHEMY_CONN=postgresql+psycopg2://postgres:postgres@postgres:5432/airflow
- AIRFLOW__CORE__FERNET_KEY=FB0o_zt4e3Ziq3LdUUO7F2Z95cvFFx16hU8jTeR1ASM=
- AIRFLOW__CORE__LOAD_EXAMPLES=False
- AIRFLOW__WEBSERVER__RBAC=True
command: worker
volumes:
- ./airflow-data/dags:/opt/airflow/dags
- ./airflow-data/logs:/opt/airflow/logs
- ./airflow-data/plugins:/opt/airflow/pluginsAnother example from https://apache-airflow.slack.com/archives/CQAMHKWSJ/p1587679356095400:
version: '3.7'
networks:
airflow:
name: airflow
attachable: true
volumes:
logs:
x-database-env:
&database-env
POSTGRES_USER: airflow
POSTGRES_DB: airflow
POSTGRES_PASSWORD: airflow
x-airflow-env:
&airflow-env
AIRFLOW__CORE__EXECUTOR: CeleryExecutor
AIRFLOW__WEBSERVER__RBAC: 'True'
AIRFLOW__CORE__CHECK_SLAS: 'False'
AIRFLOW__CORE__STORE_SERIALIZED_DAGS: 'False'
AIRFLOW__CORE__PARALLELISM: 50
AIRFLOW__CORE__LOAD_EXAMPLES: 'False'
AIRFLOW__CORE__LOAD_DEFAULT_CONNECTIONS: 'False'
AIRFLOW__SCHEDULER__SCHEDULER_HEARTBEAT_SEC: 10
services:
postgres:
image: postgres:11.5
environment:
<<: *database-env
PGDATA: /var/lib/postgresql/data/pgdata
ports:
- 5432:5432
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./database/data:/var/lib/postgresql/data/pgdata
- ./database/logs:/var/lib/postgresql/data/log
command: >
postgres
-c listen_addresses=*
-c logging_collector=on
-c log_destination=stderr
-c max_connections=200
networks:
- airflow
redis:
image: redis:5.0.5
environment:
REDIS_HOST: redis
REDIS_PORT: 6379
ports:
- 6379:6379
networks:
- airflow
webserver:
image: airflow:1.10.10
user: airflow
ports:
- 8090:8080
volumes:
- ./dags:/opt/airflow/dags
- logs:/opt/airflow/logs
- ./files:/opt/airflow/files
- /var/run/docker.sock:/var/run/docker.sock
environment:
<<: *database-env
<<: *airflow-env
ADMIN_PASSWORD: airflow
depends_on:
- postgres
- redis
command: webserver
healthcheck:
test: ["CMD-SHELL", "[ -f /opt/airflow/airflow-webserver.pid ]"]
interval: 30s
timeout: 30s
retries: 3
networks:
- airflow
flower:
image: airflow:1.10.10
user: airflow
ports:
- 5555:5555
depends_on:
- redis
volumes:
- logs:/opt/airflow/logs
command: flower
networks:
- airflow
scheduler:
image: airflow:1.10.10
volumes:
- ./dags:/opt/airflow/dags
- logs:/opt/airflow/logs
- ./files:/opt/airflow/files
- /var/run/docker.sock:/var/run/docker.sock
environment:
<<: *database-env
command: scheduler
networks:
- airflow
worker:
image: airflow:1.10.10
user: airflow
volumes:
- ./dags:/opt/airflow/dags
- logs:/opt/airflow/logs
- ./files:/opt/airflow/files
- /var/run/docker.sock:/var/run/docker.sock
environment:
<<: *database-env
command: worker
depends_on:
- schedulerRelated issues
The initial user creation #8606, #8548
Quick start documentation planned in #8542
Activity
[-]Add Production-ready docker compose for The production image[/-][+]Add Production-ready docker compose for the production image[/+]potiuk commentedon Apr 28, 2020
This one duplicates #8548 a bit - but I want to leave it for a while as I wanted to split it into smaller functional pieces.
kaxil commentedon Apr 28, 2020
It would be nice to have this in "Quick Start Guide when using Docker Image" too. WDYT
potiuk commentedon Apr 28, 2020
Absolutely. It's already planned in #8542 :)
potiuk commentedon Apr 28, 2020
Added missing label :)
habibdhif commentedon May 3, 2020
Here is another example of a Docker Compose that I've been working on. The Compose defines multiple services to run Airflow.
There is an init service which is an ephemeral container to initialize the database and creates a user if necessary.
The init service command tries to run
airflow list_usersand if it fails it initializes the database and creates a user. Different approaches were considered but this one is simple enough and only involves airflow commands (no database-specific commands).Extension fields are used for airflow environment variables to reduce code duplication.
I added a Makefile along the docker-compose.yml in my repo so all you have to do to run the docker-compose is run
make run.infused-kim commentedon May 10, 2020
Here's my docker-compose config using LocalExecutor...
docker-compose.airflow.yml:
docker-compose.yml:
Dockerfile:
Makefile
And here's my Makefile to control it the containers like
make run:wittfabian commentedon May 14, 2020
@potiuk Is this the preferred way to add dependencies (airflow-mssql)?
potiuk commentedon May 14, 2020
I the preferred way will be to set properly AIRFLOW_EXTRAS variable and pass them as --build-arg
They are defined like that in the Dockerfile:
and when building the dockerfile you can set them as
--build-arg AIRFLOW_EXTRAS="...."I think that maybe it's worth to have "additional extras" and append them though
infused-kim commentedon May 14, 2020
Oh, that's super cool.
But for that you have to rebuild the entire airflow image? Can you just add the build arg in the docker-compose and it will propagate through to the published airflow image?
44 remaining items
potiuk commentedon Nov 12, 2020
Agree. Starting small is good.
ryw commentedon Nov 30, 2020
@potiuk should we move milestone to 2.1 for this?
potiuk commentedon Nov 30, 2020
Yep. Just did :).
mik-laj commentedon Dec 10, 2020
My docker compose:
mik-laj commentedon Dec 16, 2020
@BasPH shared on Slack: one-line command to start Airflow in docker:
https://apache-airflow.slack.com/archives/CQAMHKWSJ/p1608152276070500
mik-laj commentedon Jan 13, 2021
I have prepared some Dockerfiles with some common configuration.
Postgres - Redis - Airflow 2.0
Postgres - Redis - Airflow 1.10.14
Mysql 8.0 - Redis - Airflow 2.0
# Migrations are broken.Mysql 8.0 - Redis - Airflow 1.10.14
I added health checks where it was simple. Anyone have an idea for health-checks for
airflow-scheduler/airflow-worker? This will improve stability.Besides, I am planning to prepare a tool that is used to generate docker-compose files using a simple wizard. I am thinking of something similar to the Pytorch project.
https://pytorch.org/get-started/locally/
potiuk commentedon Jan 13, 2021
Very good idea! ❤️
ldacey commentedon Feb 20, 2021
Has anyone successfully gotten turbodbc installed using pip? I have had to install miniconda and use conda-forge to get turbodbc + pyarrow working correctly. This adds a little complication to my Dockerfile, although I do kind of like the conda-env.yml file approach.
@mik-laj wow, I knew I could use common environment variables but I had no idea you could also do the volumes and images, that is super clean. Any reason why you have the scheduler restart every 30 seconds like that?
ldealmei commentedon Feb 23, 2021
Thank you all for the
docker-composefiles :)I'm sharing mine as it addresses some aspects that I couldn't find in this thread and had me spend some time on it to get it to work. These are:
git-sync(This one is optional but is quite convienent).@mik-laj I also have a working healthcheck on the scheduler. Not the most expressive but works.
This configuration relies on an existing and initialized database.
External database - LocalExecutor - Airflow 2.0.0 - Traefik - Dags mostly based on DockerOperator.
I have an extra container (not shown) to handle rotating logs that are output directly to files. It is based on logrotate. Not sharing it here because it is a custom image and is beyond the scope of the thread. But if anybody interested, message me.
Hope it helps!
mik-laj commentedon Feb 28, 2021
I added some improvements to the docker-compose file to make it more stable.
#14519
#14522
Now we have health-checks for all components.
kaxil commentedon Mar 30, 2021
@mik-laj Can we close this one since we already added the docker-compose files?
potiuk commentedon Mar 30, 2021
@kaxil -> I believe so. I do not think 'production-ready" docker-compose is even a thing :)