Airflow module
Lesson 3
Your first DAG
Write a two-task TaskFlow DAG, wait for the processor to parse it, unpause, and trigger a run in the UI.
beginner40 minRun on your machine
What you will be able to do
- Write a TaskFlow DAG file in dags/ using @dag and @task
- Unpause the DAG and trigger a run from the UI
- Open the graph and read a task log
Why this matters for data work
A DAG file is just Python on disk. Airflow does not run it like python job.py. The DAG processor imports the file, stores the graph, and the scheduler later runs tasks. Until you have watched that loop once — file, parse, trigger, log — the UI is a mystery.
Keep schedule=None so nothing fires overnight. You will add clocks in Schedules and runs.
Concepts
TaskFlow — decorate a function with @dag and inner functions with @task. Calling those functions wires dependencies and (small) return values. Import from airflow.sdk (Airflow 3 Task SDK).
Paused at creation — our compose sets DAGS_ARE_PAUSED_AT_CREATION. New DAGs show up off. You flip the toggle, then Trigger.
Parse delay — after you save the file, wait. The DAG processor polls dags/. A syntax error means the DAG never appears; the processor log names the file.
Classic DAG() + BashOperator still exists. You will see it next lesson. First graph: two Python tasks.
Practice on your machine
Stack should already be up from Getting Started.
cd ~/dcubes/airflow-lab
cat > dags/hello_airflow.py << 'EOF'
from datetime import datetime
from airflow.sdk import dag, task
@dag(
schedule=None,
start_date=datetime(2024, 1, 1),
catchup=False,
tags=["dcubes"],
)
def hello_airflow():
@task
def say_hello() -> str:
print("Hello from the DCubes Airflow lab")
return "hello"
@task
def shout(word: str) -> None:
print(word.upper())
shout(say_hello())
hello_airflow()
EOF
Wait about 30–60 seconds, then refresh http://127.0.0.1:18080.
You should see a DAG named hello_airflow. If it is missing:
docker compose logs airflow-dag-processor --tail 50
Fix the file, save, wait again.
Run it
- Toggle the DAG on (unpause).
- Open hello_airflow.
- Use Trigger (sometimes labeled Trigger DAG).
- Open the graph.
say_helloshould sit upstream ofshout. - Click
say_hello, then Logs. You want the lineHello from the DCubes Airflow lab. shoutlogs should includeHELLO.
Both tasks success (green). That is the whole loop.
What you should see
dags/hello_airflow.py
UI: hello_airflow (paused at first)
After trigger: say_hello --> shout both success
On disk, logs/ will grow files. You do not need to read them yet; the UI is enough.
Common mistakes
- Forgetting to call
hello_airflow()at the bottom. The decorator defines the factory; the call registers the DAG. schedule="@daily"on a first try. You will get confused by logical dates. Stay onNoneand trigger by hand.- Editing the file inside the container. Edit
~/dcubes/airflow-lab/dags/on the host; the bind mount is the source of truth. - Import errors.
from airflow.sdk import dag, taskis the Airflow 3 path. Oldfrom airflow.decorators import dagstill appears in 2.x posts.