---
title: "Apache AirFlow で別コンテナを立ち上げて実行 | grasys blog"
url: "https://blog.grasys.io/post/k-watanabe/apache-airflow/"
description: "業務でApache AirFlowを初めて触りました。既にコンテナ化していたスクリプトをパイプラインに組み込みたく色々調べたところ、AirFlowのオペレータにDockerOperatorがありました。個人的に詰まったポイントなど共有できればと思います AirFlowもDockerで実行する - まずAirFlowを…"
---

# Apache AirFlow で別コンテナを立ち上げて実行

-   ![](/_astro/noicon.CTHOhNiB_1HMs6A.webp)[k-watanabe](/authors/k-watanabe/)
-   公開日：2026年2月25日
-   カテゴリー：[Tech](/categories/tech/)
-   タグ：[#Apache Airflow](/tags/apache-airflow/)[#Docker](/tags/docker/)[#Docker Compose](/tags/docker-compose/)[#grasys](/tags/grasys/)[#Python](/tags/python/)

![Apache AirFlow で別コンテナを立ち上げて実行](/_astro/hero.D4zcdXaM_Z1ndjwv.webp)

業務でApache AirFlowを初めて触りました。既にコンテナ化していたスクリプトをパイプラインに組み込みたく色々調べたところ、AirFlowのオペレータにDockerOperatorがありました。個人的に詰まったポイントなど共有できればと思います

## AirFlowもDockerで実行する

-   まずAirFlowをDocker Composeで立ち上げます。[公式](https://airflow.apache.org/docs/apache-airflow/stable/howto/docker-compose/index.html)からdocker-compose.yamlをダウンロードします

Plain textcontent\_copy

```
curl -LfO 'https://airflow.apache.org/docs/apache-airflow/3.1.6/docker-compose.yaml'
```

-   ディレクトリの作成

Plain textcontent\_copy

```
mkdir -p ./dags ./logs ./plugins ./config
echo -e "AIRFLOW_UID=$(id -u)" > .env
```

-   airflow.cfg を初期化する

Plain textcontent\_copy

```
docker compose run airflow-cli airflow config list
```

-   データベースを初期化する

Plain textcontent\_copy

```
docker compose up airflow-init
```

-   サンプルDagを非表示にする

docker-compose.yamlから **AIRFLOW\_\_CORE\_\_LOAD\_EXAMPLES**を探し出して修正します

Plain textcontent\_copy

```
# 修正前
AIRFLOW__CORE__LOAD_EXAMPLES: 'true'

# 修正後
AIRFLOW__CORE__LOAD_EXAMPLES: 'false'
```

-   Volumeのマウント

別コンテナを起動するためにホスト側のDocker Engineを操作できるようにする必要があります。

そのためソケットファイルをマウントします

docker-compose.yamlの**x-airflow-commonのvolumes**に追加

Plain textcontent\_copy

```
volumes:
    - ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags
    - ${AIRFLOW_PROJ_DIR:-.}/logs:/opt/airflow/logs
    - ${AIRFLOW_PROJ_DIR:-.}/config:/opt/airflow/config
    - ${AIRFLOW_PROJ_DIR:-.}/plugins:/opt/airflow/plugins
    - /var/run/docker.sock:/var/run/docker.sock <-- 追加
```

-   実行

Plain textcontent\_copy

```
docker compose up
```

-   ブラウザからアクセス

Plain textcontent\_copy

```
http://localhost:8080
```

## Pythonをビルドする

CSVファイルを読み込んで操作した結果をファイルに書き出すPythonコードをビルドします

scoreによってランク付けします

-   0~30: C
    
-   31~50: B
    
-   51~80: A
    
-   81~100:S
    

datas/sample.csv

Geminiで生成しました

Plain textcontent\_copy

```
id,team,score
1,teamA,82
2,teamB,65
3,teamC,91
4,teamD,74
5,teamE,48
6,teamF,88
7,teamG,56
8,teamH,95
9,teamI,72
10,teamJ,83
11,teamK,41
12,teamL,67
13,teamM,59
14,teamN,92
15,teamO,30
16,teamP,78
17,teamQ,85
18,teamR,52
19,teamS,61
20,teamT,70
```

※実在しないサンプルデータです

main.py

Plain textcontent\_copy

```
import pandas as pd

df = pd.read_csv('datas/sample.csv')

def assign_rank(score):
    if score <= 30:
        return 'C'
    elif score <= 50:
        return 'B'
    elif score <= 80:
        return 'A'
    else:
        return 'S'

df['rank'] = df['score'].apply(assign_rank)

df.to_csv('results/ranked.csv', index=False)

print(df)
```

Dockerfile

Plain textcontent\_copy

```
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["python", "main.py"]
```

ビルド

Plain textcontent\_copy

```
docker build -t python-sample:latest .
```

## Dagの作成

/dags/python-sample.pyでDagファイルを作成します

Plain textcontent\_copy

```
import os
from docker.types import Mount
from airflow.sdk import dag
import datetime
from airflow.providers.docker.operators.docker import DockerOperator

@dag(
    schedule=None,
    start_date=datetime.datetime(2025, 1, 1),
    catchup=False,
    tags=["test"],
)
def python_sample():

    base_path = os.getenv("BASE_PATH")

    DockerOperator(
        task_id="python-sample",
        container_name="python_sample",
        entrypoint=['python', 'main.py'],
        image="python-sample:latest",
        network_mode="my_network",
        auto_remove="force",
        docker_url="unix://var/run/docker.sock",
        mount_tmp_dir=False,
        mounts=[
            Mount(target="/app/datas", source=f"{base_path}datas/", type="bind"),
            Mount(target="/app/results", source=f"{base_path}results", type="bind"),
        ],
    )

python_sample()
```

DockerOperatorについて説明していきます

-   task\_id: タスクのID
    
-   container\_name: 起動するコンテナ名
    
-   entrypoint: エントリーポイント
    
-   image: 先ほどビルドしたイメージ名
    
-   network\_mode: ネットワークを指定。必要なければ省略可です。
    
-   auto\_remove: コンテナを削除するかどうか
    
-   docker\_url: マウントしたソケットファイル
    
-   mount\_tmp\_dir:
    
-   mounts: 起動したコンテナにマウントしたい場合に指定。
    
    -   環境変数BASE\_PATHには **/Users/username/path/to/airflow**のように絶対パスを入れます

AirFlowを起動する

Plain textcontent\_copy

```
docker compose up -d --build
```

ブラウザでアクセスしてサイドバーの**Dags**でDagを開きます

Plain textcontent\_copy

```
http://localhost:8089/
```

![Dagの作成の画面（1）](/_astro/01-eec5c142c03092fe2c2003945a71c4fc-1024x521-7a5cb122._6e2KMrS_Z1BtXzM.webp)

トリガーボタンでDagを実行します。するとDockerOperatorのcontainer\_nameのコンテナが起動しています。

auto\_remove: force にしているので実行が終わるとコンテナは削除されます。

![Dagの作成の画面（2）](/_astro/02-48b58fc191da01e231d923e786a65075-1024x107-e5b34568.BmqMEAV0_Z2eTHOA.webp)

ログにはpythonコードのログが出力されています

![Dagの作成の画面（3）](/_astro/03-e8a3c07d46e9cfe5a35fb4dc1d0261c8-1024x626-2c9912f3.26pl1rdq_Z1ebPqx.webp)

## まとめ

既に実装していたコードを修正せずにパイプラインを構築したかったため、DockerOperatorはとても重宝しました。

起動したコンテナにマウントする場合絶対パスで指定するところで躓きました。。。ログがAirFlowにそのまま出力されるのでパイプラインコードと処理コードを切り分けて実装できるのが良いなと思いました。他にも便利なOperatorがあるので引き続き勉強していきたいです。

## この記事を書いた人

[![](/_astro/k-watanabe.6rq5wFlh_1kh1W2.webp)](/authors/k-watanabe/)

### [k-watanabe](/authors/k-watanabe/)

渡辺を勝ち取れなかったエンジニアです。

[プロフィールと記事一覧](/authors/k-watanabe/)