home
diamond Go Premium
Data Engineering Path  ·  Airflow
Apache Airflow Logo

SSH, Docker & Generic SQL Operators

The Three Operators That Don't Belong to Any One Cloud

Everything covered so far in this module is tied to a specific provider - AWS, a specific database, a specific cloud. These three aren't: SSHOperator reaches any server, DockerOperator runs any image on any Docker daemon, and SQLExecuteQueryOperator speaks to any database with a JDBC-style connection. They're the generic fallback when nothing more specific fits.

A Note on This Page's Screenshots
SSHOperator and DockerOperator need a real remote host / Docker daemon to target, neither available in this sandbox - that code is correct but shown without a live run, same honest treatment as EMR/Redshift/Glue/ECS-Batch/KubernetesPodOperator. SQLExecuteQueryOperator, below, was run for real against a genuine (if minimal) database.

SSHOperator — Run a Command on a Remote Host

from airflow.providers.ssh.operators.ssh import SSHOperator

check_disk_space = SSHOperator(
    task_id="check_disk_space",
    ssh_conn_id="prod_server_ssh",
    command="df -h /data",
)

ssh_conn_id points at an Airflow Connection of type SSH, storing the host, username, and either a password or a private key. Everything about authentication lives in the Connection, never in the DAG code.

Tip — when this beats a purpose-built operator
If a purpose-built operator already exists for what you're doing (an AWS/GCP service, a database with its own hook), use that instead - it handles retries, connection pooling, and error parsing specific to that system. Reach for SSHOperator when the target is a plain server with no such operator: a legacy on-prem box, a self-managed VM running something with no Airflow provider.

DockerOperator — Run a Container on a Docker Daemon

from airflow.providers.docker.operators.docker import DockerOperator

run_transform_container = DockerOperator(
    task_id="run_transform_container",
    image="my-registry/transform-tool:v2.1",
    command="python transform.py --date {{ ds }}",
    docker_url="unix://var/run/docker.sock",   # the Docker daemon to target
    network_mode="bridge",
    auto_remove="success",
)

This is the non-Kubernetes sibling of KubernetesPodOperator (covered on the previous page) — same idea, "run this container image as a task," but targeting a plain Docker daemon (often the same host the Airflow worker runs on) instead of a Kubernetes cluster.

DockerOperator KubernetesPodOperator
Target A single Docker daemon A Kubernetes cluster (any number of nodes)
Scaling Limited to that daemon's host resources Scales across the whole cluster
Typical fit Small teams, simple infra, no Kubernetes Teams already running Kubernetes

SQLExecuteQueryOperator — Any Database, One Operator

The generic SQL operator, for any database with a standard DB-API/JDBC-style connection (Postgres, MySQL, SQLite, and more) — the same interface regardless of which one:

from airflow.providers.common.sql.operators.sql import SQLExecuteQueryOperator

validate_row_count = SQLExecuteQueryOperator(
    task_id="validate_row_count",
    conn_id="orders_db",
    sql="SELECT COUNT(*) FROM orders WHERE amount > 0",
)

Run for real, against a genuine (if minimal) SQLite database created specifically for this task:

Airflow Graph View — setup_demo_table and validate_row_count (SQLExecuteQueryOperator) both succeeding Figure — the first task creates and populates a real table; SQLExecuteQueryOperator then queries it for real over the sqlite_demo connection.

Don't Confuse the Generic Operator With Provider-Specific Ones
SQLExecuteQueryOperator works everywhere but knows nothing special about any one database. RedshiftDataOperator, BigQueryInsertJobOperator, and similar provider-specific operators (covered on their own pages) add things the generic one can't: async polling via that service's own API, service-specific error handling, and integration with that provider's other operators. Prefer the specific operator when one exists for your database; fall back to the generic one when it doesn't.
lock

This content is reserved for Premium Members.

Upgrade to Premium

Entity Details

Create New Item

help

Submit Technical Query

Have a question or run into an issue? Describe it below, upload an optional screenshot, and our engineering team will answer it!

image Attach image (optional)

Submit Feedback

build Free Developer Utility Free Tool
gavel

Privacy & Legal Disclaimer

1. Client-Side Browser Processing

All utility tools on DeepEngineerHub (including Image to PDF, Text Formatters, JSON Converters, and Encryptors) execute 100% locally within your client browser using WebAssembly and JavaScript. No uploaded images, text, or documents are transmitted, collected, or stored on remote servers.

2. Limitation of Liability ("As-Is" Provision)

Tools and services are provided free of charge for convenience and educational purposes "as-is" without warranties of any kind. DeepEngineerHub shall not be held liable for any data loss, formatting inconsistencies, or indirect damages resulting from tool usage.

3. Open Source & Third-Party Software

Certain utilities utilize open-source client libraries (such as jsPDF, Mermaid.js, Pyodide) licensed under MIT, Apache, or BSD open licenses. All intellectual property remains with their respective copyright holders.