Dag
혹은 Task
코드를 Docker Image
로 만들고 이를 독립된 공간 (Docker Container) 안에서 실행Scale Up
, Scale Out
, K8s
와 같은 컨테이너 기술이 필요하다.K8s
란 어떤 역할이 명확하게 정해지지는 않았지만 언제든지 사용할 수 있는 공용 서버 클러스터이다.태스크나 DAG 코드를 Docker Image로 만들어서 Docker Container 형태로 실행한다. 이렇게 되면 라이브러리/모듈 충돌을 방지할 수 있고, 개발 환경과 프로덕션 환경을 동일하게 유지할 수 있다.
Airflow Worker를 K8s에서 필요한 대로 동적으로 할당해서 사용한다. 전용 서버를 Airflow에 할당하지 않고 Container Orchestration 서비스를 통해 할당해서 사용하고 리턴한다.
Airflow에서 이를 해결하는 방법은?
KubernetesPodOperator
사용DockerOperator
를 사용Airflow Executo
로 아래를 사용✍ Airflow Executor는 무엇인가?
- Executor는 Task들을 관리하고 실행하는 역할을 수행한다.
- 이 타입에 따라 병렬 혹은 일렬 실행이나 어떤 worker로 실행할지 결정됨
- 다양한 수의 Executor 타입이 존재한다.
Sequential Executor
: default. sqlite와 같은 싱글 스레드 DB에서만 사용 가능하다.Local Executor
: task들을 Airflow 마스터 노드안에서 실행Celery Executor
: 다수의 Worker 노드가 있는 경우 사용되며 Celery 큐를 사용해 task들을 worker 노드로 분산하여 실행Kubernetes Executor
는 K8s 클러스터를 사용하여 task들을 독립된 환경에서 사용Local Kubernetes Executor
와Celery Kubernetes Executor
도 존재
내가 만든 프로그램이 다른 컴퓨터에서 안 돌아간다면?
설치 과정에서 중요한 파일이 빠지거나
사용하는 라이브러리의 버전이 안 맞거나
환경 설정이 안 맞을 때
이때 가장 쉬운 해결 방법이 Docker
이기 때문에 Docker
사용
왜 Docker의 사용이 가장 쉬운 해결 방법인가?
✍ Docker Image와 Docker Container
- Docker Image: 독립적으로 완전하게 만들어진 패키지를 말한다.
- Docker Container: 이 Docker Image를 독립된 환경에서 실행한 것이다.
Virtual Machine
은 Host 운영 체제가 존재하고, 그 위에 VM을 생성하고 관리하는 소프트웨어가 있어야 한다. Hypervisors, VMWare, Virtual Box 등.docker build -t tag(이미지 이름과 버전 지정)
FROM
: 뭘 기반으로 시작되었는지. (Python, Linux 등)RUN
: 어떤 프로그램을 설치할 것인지.ENTRYPOINT
, CMD
: 프로그램을 실행.ARG
, ENV
)docker run
FROM node:alpine #OS 종류를 적어 준다. Alpine은 경량 리눅스이고 데모 목적
COPY ./app # 코드 복사에 사용
WORKDIR /app # Working directory를 지정
CMD node app.js # 실행하는 명령 앞에 지정
RUN apt-get update && apt-get install -y curl
(RUN 뒤에는 다양한 명령이 올 수 있다. 해당 명령도 &&을 사용해 두 개의 명령을 지정한 것이다.)docker run
명령을 쓰고 뒤에 docker image를 적어 docker image를 실행할 때 어떤 명령어를 실행할 것인지 적어 준다. CMD
와 ENTRYPOINT
를 두 번 쓰면 마지막 명령만 실행된다.CMD ["command1.sh"]
CMD ["command2.sh"]
#이런 경우 command2.sh만 실행됨
FROM debian:buster
COPY . /myproject
RUN apt-get update …
CMD ["./cmd1.sh"]
docker run my-image
를 하면 cmd1.sh
가 기본으로 실행되지만 docekr run my-image cmd2.sh
를 실행하면 cmd2.sh가 실행된다.ENTRYPOINT
가 우선 순위가 되는데 Best는 ENTRYPOINT
는 최대한 쓰지 않고 CMD
만 쓰는 게 일반적이다.FROM debian:buster
COPY . /myproject
RUN apt-get update …
ENTRYPOINT ["entrypoint1.sh"]
CMD ["param1", "param2"]
ENTRYPOINT
가 명령이 되고 CMD
가 파라미터를 제공하는 형식으로 쓰인다. #output
docker run my-image
=> entrypoint.sh param1 param2
docker run my-image cmd2
=> entrypoint.sh cmd2 #output
docker run --entrypoint="/cmd3.sh” my-image
docker image ls
docker tag hello-world-docker:latest dockerhub-repo:latest
-> 현재 이미지의 repo 이름을 dockerhub repo로 별칭을 만들어 줌 (이름을 바꾸는 게 아니라 별칭)docker image ls
docker login --username=dockerhub
docker push dockerhub
Docker Hub
에 Docker Image
가 올라간 것을 볼 수 있다.docker version
(docker 버전 확인)docker pull dockerhub-repo
(접근 권한이 있다면 image가 다운로드가 될 것)docker image ls
docker run dockerhub-repo
📌 빌드 시 오류 발생
WARNING: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64/v3) and no specific platform was requested exec /usr/local/bin/docker-entrypoint.sh: exec format error
이런 오류를 막기 위해 이미지 생성 시 --platform을 통해 platform을 지정해 주어야 한다.$ docker build --platform linux/amd64 -t hello-world-docker .
docker run
은 새로 Container를 실행하는 것이다.docker exec
는 실행된 Container
에 작업하는 것이라 Container ID가 꼭 필요하다.Docker Image
의 버전이나 변형을 나타내는 문자열Docker Image
의 부가 정보를 나타냄 docker image ls
에서 Repo에 해당된다.Repo이름:태그
docker run ubuntu
ubuntu
이미지가 존재하지 않기 때문에 Docker Hub
에서 ubuntu
이미지를 가지고 와 준다. docker ps
를 쓰면 ubuntu
의 Container
가 보이지 않지만 docker ps -a
를 쓰면 실행이 끝났던 Container
도 보이게 된다.docker run -it ubuntu
ubuntu
는 그냥 시작하면 바로 끝나게 된다.apt install nano
로 다시 설치를 해 주는데 다음과 같은 오류가 또 발생한다면 update
를 해 주어야 한다.apt update
를 통해 update를 해 준다. 다양한 소프트웨어를 어디서 받을 수 있는지를 업데이트해 주는 것이다.apt install nano
를 설치하면 제대로 설치가 된다. 이때 nano는 편집기이다.apt remove nano
를 해 주면 삭제된다.docker pull mysql/mysql-server:8.0
docker run --name=mysql_container mysql/mysql-server:8.0
--name=
은 Docker Container의 아이디를 주어 ps로 아이디를 찾는 과정을 스킵할 수 있게 해 준다.docker logs mysql_container 2>&1 | grep GENERATED
docker exec -it mysql_container mysql -uroot -p
1. ENTRYPOINT를 사용하면 더 편해지는 경우
- 강의에서는 ENTRYPOINT를 꼭 사용해야 하는 경우는 존재하지 않고 최대한 CMD만 사용하라고 했지만 ENTRYPOINT를 사용하면 더 편해지는 경우가 존재한다고 했다. 그 부분이 궁금해서 조금 더 학습해 보기로 하였다.
- 인수 고정
ENTRYPOINT
를 사용하면 Dockerfile에서 컨테이너에 대해 항상 실행되는 기본 실행 명령을 지정할 수 있다.- 예를 들어,
ENTRYPOINT ["java", "-jar", "myapp.jar"]
와 같이ENTRYPOINT
를 설정하면 컨테이너가 항상java -jar myapp.jar
를 실행한다.- 컨테이너 실행 시에 추가 인수를 제공해도
ENTRYPOINT
에서 정의한 명령은 변경되지 않고,ENTRYPOINT
는 고정된 부분을 유지하며 컨테이너의 기본 실행 명령을 지정한다.- 하지만
CMD
명령을 사용하면 default로 설정해 둔 명령이 overriding 된다.- 컨테이너 설정 초기화
ENTRYPOINT
는 컨테이너가 시작될 때 설정을 초기화하는 데 사용된다.- 예를 들어, 환경 변수, 파일 복사, 네트워크 구성 등 초기화 작업을 ENTRYPOINT 스크립트에 포함시킬 수 있다.
- 이를 통해 컨테이너가 시작될 때마다 일관된 설정을 보장할 수 있다.
- 정리해 보면 명령어가 먼저 default 값을 설정하지만 상황에 따라 명령어가 달라질 여지가 있을 때는
CMD
를 그렇지 않고 변경이 필요 없거나 꼭 실행되어야 하는 명령어일 경우ENTRYPOINT
를 사용한다.
2. grep 명령어 Window에서는 어떻게 사용해야 할까?
- 실습 과정에서
docker logs mysql_container 2>&1 | grep GENERATED
해당 명령어를 통해 log에서GENERATED
라는 문장을 찾는 부분이 있었다.- 입력하니
'grep'은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는 배치 파일이 아닙니다.
다음과 같은 오류가 발생했고 확인해 보니 window에서는grep
명령어가 존재하지 않았다.- 대신 써 줄 수 있는 명령어는
findstr
였다.findstr
는 뒤에 무엇이 붙느냐에 따라 명령어가 조금 달라지게 되는데 기본적으로는 파일에서 문자열을 찾는 명령어이다.docker logs mysql_container 2>&1 | findstr GENERATED
해 주니 원하는 결과인GENERATED ROOT PASSWORD: password
가 나왔다.