Airflow๋ฅผ Docker๋กœ ์šด์˜ํ•˜๋ฉด์„œ ์ž์ฃผ ๋งˆ์ฃผ์น˜๋Š” ์ด์Šˆ๋ฅผ ์ •๋ฆฌ


โ— ๋ฌธ์ œ 1 โ€” .env ํŒŒ์ผ์ด Airflow ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ ์•ˆ ๋ณด์ธ๋‹ค

๐Ÿ” ์ฆ์ƒ ์š”์•ฝ

  • .env ํŒŒ์ผ์€ ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— ์กด์žฌ.
  • ํ•˜์ง€๋งŒ Airflow ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ๋Š” load_dotenv()๊ฐ€ ์ฝ์ง€ ๋ชปํ•จ.
  • ์ด์œ :
    • Docker๋Š” .env ํŒŒ์ผ์„ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋กœ ๋ณ€ํ™˜ํ•ด ๋„˜๊ธฐ๊ธด ํ•˜์ง€๋งŒ,
    • ํŒŒ์ผ ์ž์ฒด๋ฅผ ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€๋กœ ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜ mountํ•˜์ง€ ์•Š๋Š”๋‹ค.
    • ๊ฒฐ๊ตญ load_dotenv()๊ฐ€ ์ฐพ์„ ํŒŒ์ผ์ด ์—†์Œ.

โœ… ํ•ด๊ฒฐ๋ฒ•

1๏ธโƒฃ docker-compose.yml์— volume mount ์ถ”๊ฐ€

services:
  airflow:
    ...
    volumes:
      - ./dags:/opt/airflow/dags
      - ./.env:/opt/airflow/dags/.env   # โœ… ์ด ์ค„ ์ถ”๊ฐ€

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด .env ํŒŒ์ผ์ด Airflow ์ปจํ…Œ์ด๋„ˆ ์•ˆ์˜ /opt/airflow/dags/.env ๊ฒฝ๋กœ๋กœ ๋ณต์‚ฌ๋œ๋‹ค.

2๏ธโƒฃ DAG ์ฝ”๋“œ์—์„œ ์ •ํ™•ํ•œ ๊ฒฝ๋กœ๋กœ load_dotenv()

์œ„์น˜๋ฅผ ์จ์ค˜์•ผํ•œ๋‹ค

from dotenv import load_dotenv
load_dotenv(dotenv_path="/opt/airflow/dags/.env")

์ด์ œ DAG ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์˜ .env ํŒŒ์ผ์„ ์ •์ƒ์ ์œผ๋กœ ์ฝ์–ด์˜จ๋‹ค.

3๏ธโƒฃ ์ปจํ…Œ์ด๋„ˆ ์žฌ์‹œ์ž‘ ํ•„์š”

docker compose down
docker compose up --build 

โ— ๋ฌธ์ œ 2 โ€” AWS Credentials ์—ฐ๋™

์˜ต์…˜ 1: .env์— ์ž๊ฒฉ์ฆ๋ช… ์ถ”๊ฐ€
.env ํŒŒ์ผ์—:

AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key

boto3๋Š” ํ™˜๊ฒฝ๋ณ€์ˆ˜์—์„œ ์ž๋™์œผ๋กœ ์ž๊ฒฉ์ฆ๋ช…์„ ๊ฐ€์ ธ์˜จ๋‹ค:

import boto3
import os
from dotenv import load_dotenv

load_dotenv(dotenv_path="/opt/airflow/dags/.env")
s3 = boto3.client("s3")  # ํ‚ค๋ฅผ ๋”ฐ๋กœ ๋„˜๊ธธ ํ•„์š” ์—†์Œ

์˜ต์…˜ 2: IAM Role์ด๋‚˜ ๋‹ค๋ฅธ ๋ฐฉ์‹๋„ ๊ฐ€๋Šฅ (์—ฌ๊ธฐ์„  ์ƒ๋žต)

โ— ๋ฌธ์ œ 3 โ€” boto3 ๋””๋ ‰ํ† ๋ฆฌ ๋ฌธ์ œ

boto3์˜ download_file() ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋กœ์ปฌ ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ๋จผ์ € ์กด์žฌํ•ด์•ผ ํ•จ.

os.makedirs(os.path.dirname(LOCAL_FILE_PATH), exist_ok=True)

์ด๋ ‡๊ฒŒ ๋ฏธ๋ฆฌ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋””๋ ‰ํ† ๋ฆฌ ์—†์Œ ์˜ค๋ฅ˜ ๋ฐฉ์ง€ ๊ฐ€๋Šฅ.

โ— ๋ฌธ์ œ 4 โ€” Airflow Metadata Database์™€ Local Files ๊ตฌ๋ถ„

Airflow์˜ metadata database (Postgres)๋Š” ์ •์ƒ์ ์œผ๋กœ ์ปจํ…Œ์ด๋„ˆ ์•ˆ์—์„œ ์ž˜ ๋Œ์•„๊ฐ โ†’ ์ด๊ฑด docker-compose๋กœ ์ด๋ฏธ ์ž˜ ์„ธํŒ…๋˜์–ด ์žˆ์Œ.

ํ•˜์ง€๋งŒ Airflow ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์—๋Š” DB ์™ธ์—๋„ local file๋“ค์ด ํ•„์š”.

๋ฐ์ดํ„ฐ ์ข…๋ฅ˜ ์ €์žฅ ๊ฒฝ๋กœ ์„ค๋ช…
๋กœ๊ทธ /opt/airflow/logs task ์‹คํ–‰ ๋กœ๊ทธ
DAG ์Šคํฌ๋ฆฝํŠธ /opt/airflow/dags DAG ์ฝ”๋“œ
์„ค์ • ๋ฐ ํ™•์žฅ /opt/airflow/plugins, airflow.cfg, webserver_config.py ์„ค์ • ๋ฐ ํ™•์žฅ ๊ธฐ๋Šฅ

๐Ÿ”ฌ ํ•ต์‹ฌ ๋ฌธ์ œ์˜ ์ง„์งœ ์›์ธ

  • metadata DB (Postgres)๋Š” ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ ์ค‘.
  • ํ•˜์ง€๋งŒ airflow webserver๊ฐ€ ๋‚ด๋ถ€ ํด๋” (์˜ˆ: /opt/airflow/logs/) ์ƒ์„ฑ์„ ์‹œ๋„ํ•  ๋•Œ โ†’ volume mount๊ฐ€ ์•ˆ ๋˜์–ด ์žˆ์–ด ์‹คํŒจ.
  • ์ด๋กœ ์ธํ•ด ๋งˆ์น˜ airflow db init ์ด ์‹คํŒจํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๋Š” ์ฐฉ์‹œ ํ˜„์ƒ์ด ๋ฐœ์ƒ.

ํ•ด๊ฒฐ๋ฒ• โ€” logs volume mount ์ถ”๊ฐ€

docker-compose.yml ์ˆ˜์ •:

services:
  airflow:
    ...
    volumes:
      - ./dags:/opt/airflow/dags
      - ./logs:/opt/airflow/logs   # โœ… ์ด ์ค„ ์ถ”๊ฐ€

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด webserver๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋กœ๊ทธ ํด๋”์— ์ ‘๊ทผ ๊ฐ€๋Šฅ โ†’ task ์‹คํ–‰๊ณผ UI ๋ชจ๋‘ ์ •์ƒ ๋™์ž‘.

๐Ÿ”ฅ ์ตœ์ข… ์š”์•ฝ

  • metadata DB์™€ local files๋Š” ์™„์ „ํžˆ ๋ณ„๊ฐœ์˜ ์˜์—ญ์ด๋‹ค.
  • local files (logs, dags, plugins)๋Š” ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€์— volume mount๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
  • .env ํŒŒ์ผ๋„ volume์œผ๋กœ ๋ช…์‹œ์ ์œผ๋กœ mountํ•˜๊ณ  load_dotenv()์—์„œ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.
  • logs volume์„ mountํ•˜์ง€ ์•Š์œผ๋ฉด webserver๊ฐ€ ๋‚ด๋ถ€ ์˜ค๋ฅ˜๋กœ ์ค‘๋‹จ๋  ์ˆ˜ ์žˆ๋‹ค.