Docker로 Airflow 실행하기
Docker로 Airflow 실행하기 (Running Airflow in Docker)
Docker Compose에서 CeleryExecutor로 Airflow를 빠르게 띄우는 방법을 설명하는 quick-start 문서예요. docker-compose.yaml을 가져오고, 환경을 초기화하고, 서비스를 실행하고, CLI·웹 UI·REST API로 접근하고, 커스텀 이미지를 사용하는 것까지 다뤄요.
출처: 문서
본문
이 quick-start 가이드는 Docker에서 CeleryExecutor로 Airflow를 빠르게 띄워 실행하게 해 줘요.
주의 (Caution)
이 절차는 학습과 탐구에 유용할 수 있어요. 하지만 실제 상황에 적용하기는 복잡할 수 있고, docker compose 파일은 프로덕션 시스템에 필요한 어떤 보안 보장도 제공하지 않아요. 이 절차를 수정하려면 Docker & Docker Compose에 대한 전문 지식이 필요하며, Airflow 커뮤니티가 도와주지 못할 수 있어요.
그 이유로 프로덕션에서 Airflow를 실행할 준비가 되면 Kubernetes와 Official Airflow Community Helm Chart를 사용하는 것을 권장해요.
시작하기 전에 (Before you begin)
이 절차는 Docker와 Docker Compose에 익숙하다고 가정해요. 이 도구들을 사용해 본 적이 없다면, Docker Quick Start를 잠시 살펴보고(특히 Docker Compose 섹션) 어떻게 동작하는지 익숙해지세요.
아직 하지 않았다면 다음 단계를 따라 필요한 도구를 설치하세요.
- 워크스테이션에 Docker Community Edition (CE)을 설치해요. OS에 따라 Airflow 컨테이너가 제대로 실행되도록 Docker가 최소 4.00GB의 메모리를 사용하도록 구성해야 할 수 있어요. 자세한 내용은 Docker for Windows 또는 Docker for Mac 문서의 Resources 섹션을 참고하세요.
- 워크스테이션에 Docker Compose v2.14.0 이상을 설치해요.
docker-compose의 이전 버전은 Airflow docker-compose.yaml 파일이 요구하는 모든 기능을 지원하지 않으므로, 버전이 최소 요구사항을 충족하는지 다시 확인하세요.
팁 (Tip)
macOS에서 Docker가 사용할 수 있는 기본 메모리 양은 Airflow를 실행하기에 충분하지 않은 경우가 많아요. 충분한 메모리가 할당되지 않으면 웹서버가 계속 재시작될 수 있어요. Docker Engine에 최소 4GB 메모리(이상적으로 8GB)를 할당해야 해요.
다음 명령으로 메모리가 충분한지 확인할 수 있어요:
docker run --rm "debian:bookworm-slim" bash -c 'numfmt --to iec $(echo $(($(getconf _PHYS_PAGES) * $(getconf PAGE_SIZE))))'
경고 (Warning)
일부 운영체제(Fedora, ArchLinux, RHEL, Rocky)는 최근 커널 변경을 도입해서, OS 팀이 유지보수하는 커뮤니티 Docker 구현 안에서 실행할 때 Docker Compose의 Airflow가 메모리를 100% 소비하게 돼요.
이는 일부 Airflow 의존성이 문제를 겪는 하위 호환되지 않는 containerd 구성 문제이며 여러 이슈로 추적되고 있어요:
containerd 팀의 해결책은 아직 없지만, Docker Desktop on Linux를 설치하면 이 코멘트에서 설명하듯 문제를 해결하고 Breeze를 문제 없이 실행할 수 있는 것 같아요.
docker-compose.yaml 가져오기 (Fetching docker-compose.yaml)
Docker Compose에서 Airflow를 배포하려면 docker-compose.yaml을 가져와야 해요.
curl -LfO 'https://airflow.apache.org/docs/apache-airflow/3.3.2/docker-compose.yaml'
중요 (Important)
2023년 7월부터 Compose V1은 업데이트를 받지 않았어요. 제공되는
docker-compose.yaml이 Compose V1에서 정확히 동작하지 않을 수 있으므로, 최신 버전의 Docker Compose로 업그레이드하는 것을 강력히 권장해요.
이 파일은 여러 서비스 정의를 포함해요:
airflow-scheduler— scheduler가 모든 태스크와 Dags를 모니터링하고, 의존성이 완료되면 task instance를 트리거해요.airflow-dag-processor— Dag processor가 Dag 파일을 파싱해요.airflow-api-server— api server가http://localhost:8080에서 사용 가능해요.airflow-worker— 스케줄러가 준 task를 실행하는 worker.airflow-triggerer— triggerer가 deferrable 태스크를 위한 이벤트 루프를 실행해요.airflow-init— 초기화 서비스.postgres— 데이터베이스.redis— The redis — 스케줄러에서 worker로 메시지를 전달하는 broker.
선택적으로 --profile flower 옵션을 추가해 flower를 활성화할 수 있어요. 예: docker compose --profile flower up, 또는 명령줄에 명시적으로 지정해 docker compose up flower.
flower— 환경을 모니터링하는 The flower app.http://localhost:5555에서 사용 가능해요.
이 모든 서비스는 CeleryExecutor로 Airflow를 실행하게 해 줘요. 자세한 내용은 Architecture Overview를 참고하세요.
컨테이너의 일부 디렉토리가 마운트되어, 그 내용이 컴퓨터와 컨테이너 사이에 동기화돼요.
./dags— Dag 파일을 여기에 둘 수 있어요../logs— 태스크 실행과 스케줄러의 로그를 포함해요../config— 커스텀 로그 파서를 추가하거나 클러스터 정책을 구성하기 위한airflow_local_settings.py를 추가할 수 있어요../plugins— 커스텀 플러그인을 여기에 둘 수 있어요.
이 파일은 최신 Airflow 이미지(apache/airflow)를 사용해요. 새 Python 라이브러리나 시스템 라이브러리를 설치해야 한다면 이미지를 빌드할 수 있어요.
환경 초기화 (Initializing Environment)
처음 Airflow를 시작하기 전에 환경을 준비해야 해요. 즉 필요한 파일, 디렉토리를 만들고 데이터베이스를 초기화해야 해요.
올바른 Airflow 사용자 설정 (Setting the right Airflow user)
Linux에서는 quick-start가 호스트 사용자 id를 알아야 하고 group id를 0으로 설정해야 해요. 그렇지 않으면 dags, logs, config, plugins에 생성된 파일이 root 사용자 소유로 만들어져요. docker-compose를 위해 다음과 같이 구성해야 해요:
mkdir -p ./dags ./logs ./plugins ./config
echo -e "AIRFLOW_UID=$(id -u)" > .env
Docker Compose 환경 변수 참고:
다른 운영체제에서는 AIRFLOW_UID가 설정되지 않았다는 경고가 나올 수 있지만, 안전하게 무시할 수 있어요. docker-compose.yaml과 같은 폴더에 이 내용으로 .env 파일을 수동으로 만들어 경고를 없앨 수도 있어요:
AIRFLOW_UID=50000
airflow.cfg 초기화 (선택) (Initialize airflow.cfg (Optional))
airflow 서비스를 시작하기 전에 airflow.cfg를 기본값으로 초기화하고 싶다면 실행해요.
docker compose run airflow-cli airflow config list
이렇게 하면 config 폴더에 기본값으로 airflow.cfg를 시드해요.
SELinux/AppArmor가 있는 시스템에서는 권한 문제가 발생할 수 있어요. 이런 경우 docker-compose.yaml 파일을 편집해 모든 volumes에 :z 접미사를 추가해요:
volumes:
- ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags:z
- ${AIRFLOW_PROJ_DIR:-.}/logs:/opt/airflow/logs:z
- ${AIRFLOW_PROJ_DIR:-.}/config:/opt/airflow/config:z
- ${AIRFLOW_PROJ_DIR:-.}/plugins:/opt/airflow/plugins:z
이 변경 후에도 airflow.cfg 파일을 만들 때 여전히 권한 문제가 발생한다면, config/ 폴더에 매우 허용적인 설정을 적용할 수 있어요:
sudo chmod -R 777 ./config
위의 것은 임시 방편(work around) 이며 프로덕션에서 절대 사용하지 말아야 한다는 점을 참고하세요.
데이터베이스 초기화 (Initialize the database)
모든 운영체제에서 데이터베이스 마이그레이션을 실행하고 첫 사용자 계정을 만들어야 해요. 이를 위해 실행해요:
docker compose up airflow-init
초기화가 완료되면 파일, 폴더, 플러그인과 관련된 출력과 마지막으로 이런 메시지를 보게 될 거예요:
airflow-init-1 exited with code 0
생성된 계정은 로그인 airflow, 비밀번호 airflow예요.
환경 정리하기 (Cleaning-up the environment)
준비한 docker-compose 환경은 "quick-start"용이에요. 프로덕션에 사용하도록 설계되지 않았고 몇 가지 함정이 있어요 — 그 중 하나는 어떤 문제에서든 복구하는 가장 좋은 방법은 정리하고 처음부터 다시 시작하는 것이에요.
가장 좋은 방법은:
docker-compose.yaml파일을 다운로드한 디렉토리에서docker compose down --volumes --remove-orphans명령을 실행docker-compose.yaml파일을 다운로드한 디렉토리 전체를 제거 —rm -rf '<DIRECTORY>'- 이 가이드를 처음부터 다시 실행 —
docker-compose.yaml파일을 다시 다운로드하면서 시작
Airflow 실행하기 (Running Airflow)
이제 모든 서비스를 시작할 수 있어요:
docker compose up
참고 (Note)
docker-compose는 옛 문법이에요. Stackoverflow를 확인하세요.
두 번째 터미널에서 컨테이너의 상태를 확인하고 어떤 컨테이너도 unhealthy 상태가 아닌지 확인할 수 있어요:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
247ebe6cf87a apache/airflow:3.3.2 "/usr/bin/dumb-init …" 3 minutes ago Up 3 minutes (healthy) 8080/tcp compose_airflow-worker_1
ed9b09fc84b1 apache/airflow:3.3.2 "/usr/bin/dumb-init …" 3 minutes ago Up 3 minutes (healthy) 8080/tcp compose_airflow-scheduler_1
7cb1fb603a98 apache/airflow:3.3.2 "/usr/bin/dumb-init …" 3 minutes ago Up 3 minutes (healthy) 0.0.0.0:8080->8080/tcp compose_airflow-api_server_1
74f3bbe506eb postgres:16 "docker-entrypoint.s…" 18 minutes ago Up 17 minutes (healthy) 5432/tcp compose_postgres_1
0bd6576d23cb redis:latest "docker-entrypoint.s…" 10 hours ago Up 17 minutes (healthy) 0.0.0.0:6379->6379/tcp compose_redis_1
환경 접근하기 (Accessing the environment)
Airflow를 시작한 후 3가지 방법으로 상호작용할 수 있어요:
CLI 명령 실행하기 (Running the CLI commands)
CLI 명령도 실행할 수 있지만, 정의된 airflow-* 서비스 중 하나에서 실행해야 해요. 예를 들어 airflow info를 실행하려면 다음 명령을 실행하세요:
docker compose run airflow-worker airflow info
Linux나 Mac OS를 사용한다면, 더 간단한 명령으로 명령을 실행할 수 있는 선택적 래퍼 스크립트를 다운로드해 작업을 쉽게 할 수 있어요.
curl -LfO 'https://airflow.apache.org/docs/apache-airflow/3.3.2/airflow.sh'
chmod +x airflow.sh
이제 명령을 더 쉽게 실행할 수 있어요.
./airflow.sh info
bash를 파라미터로 사용해 컨테이너에서 대화형 bash 셸에 들어가거나, python으로 python 컨테이너에 들어갈 수도 있어요.
./airflow.sh bash
./airflow.sh python
웹 인터페이스 접근하기 (Accessing the web interface)
클러스터가 시작되면 웹 인터페이스에 로그인해 Dags로 실험을 시작할 수 있어요.
웹서버는 http://localhost:8080에서 사용할 수 있어요. 기본 계정은 로그인 airflow, 비밀번호 airflow예요.
REST API에 요청 보내기 (Sending requests to the REST API)
기본 username password 인증이 현재 REST API에서 지원되므로, 일반 도구로 API에 요청을 보낼 수 있어요.
웹서버는 http://localhost:8080에서 사용할 수 있어요. 기본 계정은 로그인 airflow, 비밀번호 airflow예요.
pool 목록을 가져오는 요청을 보내는 예시 curl 명령이에요:
ENDPOINT_URL="http://localhost:8080"
JWT_TOKEN=$(curl -s -X POST ${ENDPOINT_URL}/auth/token \
-H "Content-Type: application/json" \
-d '{"username": "airflow", "password": "airflow"}' |\
jq -r '.access_token' \
)
curl -X GET \
"${ENDPOINT_URL}/api/v2/pools" \
-H "Authorization: Bearer ***"
정리 (Cleaning up)
컨테이너를 중지·삭제하고, 데이터베이스 데이터가 있는 volumes를 삭제하고, 이미지를 다운로드하려면 실행해요:
docker compose down --volumes --rmi all
커스텀 이미지 사용하기 (Using custom images)
Airflow를 로컬에서 실행할 때 일부 추가 의존성을 포함하는 확장 이미지를 사용하고 싶을 수 있어요 — 예를 들어 새 python 패키지를 추가하거나 airflow providers를 최신 버전으로 업그레이드할 수 있어요. 이는 docker-compose.yaml에 build: .를 지정하고 docker-compose.yaml 옆에 커스텀 Dockerfile을 두면 매우 쉽게 할 수 있어요. 그런 다음 docker compose build 명령으로 이미지를 빌드할 수 있어요(한 번만 하면 됨). 다른 docker compose 명령을 실행할 때 이미지를 즉석에서 재빌드하려면 docker compose 명령에 --build 플래그를 추가할 수도 있어요.
커스텀 provider, python 패키지, apt 패키지 등으로 이미지를 확장하는 방법의 예시는 Building the image에서 찾을 수 있어요.
참고 (Note)
커스텀 이미지를 만들면, 설치하려는 패키지나 Airflow가 업그레이드될 때 이미지를 다시 만들어야 하므로 자동화 수준도 유지해야 해요. 이 스크립트를 보관하는 것을 잊지 마세요. 또한 순수 Python 태스크를 실행할 때는 런타임 중 python 의존성을 동적으로 소스·설치하는 Python Virtualenv functions를 사용할 수 있다는 점도 명심하세요. Airflow 2.8.0부터 virtualenv도 캐시할 수 있어요.
특수 사례 — requirements.txt 파일로 의존성 추가하기 (Special case - adding dependencies via requirements.txt file)
커스텀 이미지의 보통 용도는 보통 requirements.txt 파일에 저장된 요구사항 세트를 추가하는 것이에요. 개발 중에는 원래 airflow 이미지를 시작할 때 동적으로 추가하고 싶을 수 있는데, 이는 여러 부작용이 있어요(예: 컨테이너 시작이 훨씬 느려짐 — 각 추가 의존성은 컨테이너 시작 시간을 더 지연시켜요). 또한 docker compose에 개발 워크플로우가 내장되어 있으므로 완전히 불필요해요. 이전 장을 따라 로컬에서 docker compose로 반복할 때 커스텀 이미지를 자동으로 빌드·사용할 수 있어요. 구체적으로 자신의 requirement 파일을 추가하고 싶을 때는 다음 단계를 해야 해요:
docker-compose.yaml파일에서image: ...줄을 주석 처리하고build: .줄의 주석을 해제해요. docker-compose 파일의 관련 부분은 다음과 비슷해야 해요(올바른 이미지 태그 사용):
#image: ${AIRFLOW_IMAGE_NAME:-apache/airflow:3.3.2}
build: .
docker-compose.yaml파일과 같은 폴더에 다음과 같은 내용으로Dockerfile을 만들어요:
FROM apache/airflow:3.3.2
ADD requirements.txt .
RUN pip install apache-airflow==${AIRFLOW_VERSION} -r requirements.txt
원본 이미지에서 나온 것과 같은 버전의 apache-airflow를 설치하는 것이 가장 좋은 관행이에요. 이렇게 하면 다른 requirements를 설치하는 동안 pip가 apache airflow를 다운그레이드하거나 업그레이드하려 하지 않도록 보장할 수 있어요. 이는 사용 중인 apache-airflow 버전과 충돌하는 의존성을 추가하려고 할 때 발생할 수 있는 문제예요.
requirements.txt파일을 같은 디렉토리에 두어요.docker compose build를 실행해 이미지를 빌드하거나,docker compose up또는docker compose run명령에--build플래그를 추가해 필요할 때 이미지를 자동으로 빌드하세요.
특수 사례 — 커스텀 구성 파일 추가하기 (Special case - Adding a custom config file)
커스텀 구성 파일이 있고 Airflow 인스턴스에서 사용하고 싶다면 다음 단계를 수행해야 해요:
- 로컬 config 폴더의 자동 생성된
airflow.cfg파일을 커스텀 구성 파일로 교체해요. - 구성 파일 이름이
airflow.cfg가 아니라면AIRFLOW_CONFIG: '/opt/airflow/config/airflow.cfg'에서 파일 이름을 조정해요.
네트워킹 (Networking)
일반적으로 로컬에서 Airflow를 사용하려면 Dags가 호스트에서 실행 중인 서버에 연결하려 할 수 있어요. 이를 위해 docker-compose.yaml에 추가 구성이 필요해요. 예를 들어 Linux에서는 services: airflow-worker 섹션에 extra_hosts: - "host.docker.internal:host-gateway"를 추가하고, localhost 대신 host.docker.internal을 사용해야 해요. 이 구성은 플랫폼마다 다르다. 자세한 내용은 Docker 문서의 Windows와 Mac을 참고하세요.
PyCharm으로 docker 컨테이너 안에서 Airflow 디버깅하기 (Debug Airflow inside docker container using PyCharm)
전제 조건: PyCharm에서 프로젝트를 만들고(docker-compose.yaml) 다운로드하세요.
단계:
docker-compose.yaml수정 —services섹션 아래에 다음 섹션을 추가해요:
airflow-python:
<<: *airflow-common
profiles:
- debug
environment:
<<: *airflow-common-env
user: "50000:0"
entrypoint: [ "/bin/bash", "-c" ]
참고 (Note)
이 코드 조각은 PyCharm의 Python 인터프리터를 위한 **"airflow-python"**이라는 새 서비스를 만들어요. Linux 시스템에서
echo -e "AIRFLOW_UID=$(id -u)" > .env명령을 실행했다면 PyCharm의Unresolved reference 'airflow'오류를 피하기 위해airflow-python서비스에user: "50000:0"을 설정해야 해요.
- PyCharm 인터프리터 구성
- PyCharm을 열고 Settings > Project:
> Python Interpreter로 이동해요. - "Add Interpreter" 버튼을 클릭하고 **"On Docker Compose"**를 선택해요.
- Configuration file 필드에서
docker-compose.yaml파일을 선택해요. - Service field에서 새로 추가한
airflow-python서비스를 선택해요. - **"Next"**를 클릭하고 프롬프트를 따라 구성을 완료해요.
- PyCharm을 열고 Settings > Project:
인터프리터 인덱스 빌드는 시간이 걸릴 수 있어요.
3) python 서비스의 docker-compose/command와 actions에 exec를 추가하세요.
구성이 끝나면 컨테이너 환경 안에서 Airflow 코드를 디버깅해 로컬 설정을 흉내낼 수 있어요.
FAQ: 자주 묻는 질문 (FAQ: Frequently asked questions)
ModuleNotFoundError: No module named 'XYZ'
Docker Compose 파일은 최신 Airflow 이미지(apache/airflow)를 사용해요. 새 Python 라이브러리나 시스템 라이브러리를 설치해야 한다면 커스터마이즈하고 확장할 수 있어요.
다음은 무엇인가요? (What's Next?)
이 지점부터 Tutorials 섹션으로 가서 추가 예시를 보거나, How-to Guides 섹션으로 가서 직접 해볼 준비를 할 수 있어요.
Docker Compose가 지원하는 환경 변수 (Environment variables supported by Docker Compose)
여기 변수 이름을 이미지가 빌드될 때 설정되는 build 인자와 혼동하지 마세요. AIRFLOW_UID build arg는 이미지가 빌드될 때 50000으로 기본값이 정해지므로 이미지에 "베이크"돼요. 반면 아래 환경 변수는 컨테이너가 실행 중일 때 설정할 수 있는데, 예를 들어 id -u 명령의 결과를 사용해 이미지를 빌드할 때 알 수 없는 동적 호스트 런타임 사용자 id를 사용할 수 있게 해 줘요.
| Variable | Description | Default |
|---|---|---|
| AIRFLOW_IMAGE_NAME | Airflow Image to use. | apache/airflow:3.3.2 |
| AIRFLOW_UID | UID of the user to run Airflow containers as. | |
| Override if you want to use non-default Airflow | ||
| UID (for example when you map folders from host, | ||
it should be set to result of id -u call. |
||
| When it is changed, a user with the UID is | ||
created with default name inside the container |
||
and home of the use is set to /airflow/home/ |
||
| in order to share Python libraries installed there. | ||
| This is in order to achieve the OpenShift | ||
| compatibility. See more in the | ||
| Arbitrary Docker User, | 50000 |
참고 (Note)
Airflow 2.2 이전에는 Docker Compose에도
AIRFLOW_GID파라미터가 있었지만, 추가 기능을 제공하지 않고 혼란만 더했기 때문에 제거됐어요.
이 추가 변수들은 Docker Compose를 통해 Airflow 설치를 시험·테스트할 때 유용해요. 프로덕션에 사용하도록 의도된 것은 아니지만, 처음 사용자가 가장 흔한 커스터마이징으로 환경을 더 빠르게 부트스트랩하게 해 줘요.
| Variable | Description | Default |
|---|---|---|
| _AIRFLOW_WWW_USER_USERNAME | Username for the administrator UI account. | |
| If this value is specified, admin UI user gets | ||
| created automatically. This is only useful when | ||
| you want to run Airflow for a test-drive and | ||
| want to start a container with embedded development | ||
| database. | airflow | |
| _AIRFLOW_WWW_USER_PASSWORD | Password for the administrator UI account. | |
| Only used when _AIRFLOW_WWW_USER_USERNAME set. | airflow | |
| _PIP_ADDITIONAL_REQUIREMENTS | If not empty, airflow containers will attempt to | |
| install requirements specified in the variable. | ||
example: lxml==4.6.3 charset-normalizer==1.4.1. |
||
| Available in Airflow image 2.1.1 and above. |