데브코스 데이터 엔지니어링 WEEK11 WIL(1)

2024. 11. 19. 16:07·Data Engineer/데브코스

Docker란? 왜 필요한가?

Airflow운영상의 어려움 (다수의 서버로 운영되는 소프트웨어)

만약 DAG의 수가 100개를 넘어간다면? 

 

1) 라이브러리 충돌

더보기

파이썬 라이브러리 충돌?

파이썬 여러 버전 설치되었을 때 import 에러가 날 수 있다. 

라이브러리는 누군가 미리 만들어 놓은 파이썬 코드

내부 라이브러리는 파이썬 설치 시 같이 설치되는 라이브러리

외부 라이브러리는 따로 직접 설치해서 사용해야하는 라이브러리 ex)selenium, requests, pandas 

이런 외부 라이브러리는 pip라는 파이썬 라이브러리를 관리해주는 프로그램을 이용한다. 

라이브러리 안에 패키지 안에 모듈

만약 python 3.10.6에서 pip install selenium 하면 잘 설치된다. 

하지만 python 3.11.3에서 from selenium import webdriver하면 오류난다. 

-> 라이브러리 설치는 했지만 현재 실행되고 있는 파이썬 버전과 다른경우 

- 파이썬 여러버전 설치 시 라이브러리는 공유되지 않는다. 

즉 파이썬 3.10.6에 라이브러리 설치해도 3.11.3에는 없다. 따로 3.11.3에서 설치 해줘야한다.

그래서 라이브러리를 설치한 파이썬 버전과 실제 vscode에서 실행할 파이썬 버전을 맞춰줘야한다. (select intrepreter)

터미널에서 실행할 때는 여러가지 파이썬 버전 환경변수가 있을때 위에 있을 수록 우선된다. 

즉 환경변수가 3.11.3으로 설정되었으면 pip install하면 3.11.3의 라이브러리가 다운된다. 

주피터 노트북을 이용해서 내가 원하는 버전의 라이브러리를 쉽게 다운

 

DAG간의 소프트웨어 버전 충돌.

ex) 어떤 DAG는 Python 2.6, 다른 DAG는 Python 3.8

-> DAG나 Task마다 다른 시스템과 분리 된 별도의 독립 공간이 있으면 어떨까?

-> 파이썬에서는 가상환경을 쓰면 어느정도 해결이 되지만 리눅스단의 라이브러리나 버전 충돌은 해결 못한다. 

-> Docker를 이용해서 다른 소프트웨어들과 완전히 분리된 별도의 공간을 만든다.(Container) 

 

Docker로 해결

- 라이브러리 모듈 충돌은 태스크나 DAG코드를 Docker Image로 만들어서 별도로 분리된 공간인 Docker Container 위에서 실행 

- 또한 개발 환경과 프로덕션 환경이 동일하게 유지 된다. 개발했을 때 동작이 되면 프로덕션 환경에서도 동작을 할것이다라고 믿을 수 있다. 

 

2) Worker의 부족

초기 구성

- 초기에는 Airflow를 단일 서버(Single Node)에서 실행

- 마스터 노드와 워커가 동일한 서버에 존재

- 워커는 CPU 코어 수만큼 작업 처리 용량을 가진다.

확장 필요성

DAG의 수가 늘어나면서 처리 용량(Worker 노드)부족해지면 두 가지 확장 방식을 고려

- Scale-Up: 서버 성능(예: CPU, 메모리)을 업그레이드하여 처리 용량 증가

- Scale-Out: 워커 노드를 별도의 서버로 분리하고, 필요한 만큼 추 가하여 클러스터를 확장

- 클라우드 서비스 고려: 관리와 운영이 복잡할 수 있기 때문에 (Scale Out approach)

 

3) 낮은 서버 활용률(Server Utilization)

- 여러 서버를 Airflow 클러스터에 할당해 운영하면 각 서버가 항상 바쁜 상태는 아니다. Airflow에 전용 Worker 노드를 10대 할당해도 항상 바쁜 상태는 아니다.

- Airflow뿐만 아니라 Webserver, Database 등 서비스별로 전용 하드웨어를 할당하면 관리가 어려워지고, 서버 자원이 놀고 있는 시간이 많아진다.

Kubernetes와 Docker를 이용한 해결

  • Kubernetes 기반 공용 서버 클러스터를 구성하여 필요한 자원을 온디맨드(On-Demand)로 요청하고 반환하는 구조를 사용한다.
  • 이를 통해 서비스별로 서버를 분리하지 않고, 공용 자원을 효율적으로 활용할 수 있다.
  • 어떤 역할이 명확하게 정해지지 않았지만 언제든지 다양한 용도로 사용될 수 있는 공용 서버 클러스터, 마스터를 통해서 다양한 서비스들이 필요한 자원을 요청하고 받아서 쓰고 끝나면 return하는 형태, webserver, database server등 server가 탄력적으로 돌아가야하는 모든 환경에서 사용가능
  •  결과적으로:
    • Capacity 관리가 용이: 자원이 필요한 서비스가 클러스터에서 요청한 만큼만 사용
    • Utilization 증가: 전체 클러스터의 CPU 및 메모리 활용률 향상

Kubernetes는 가장 인기 있는 Container Orchestration 서비스 중 하나로, 자원의 동적 관리와 확장을 지원

Airflow와 Kubernetes의 통합

Kubernetes를 이용해 Airflow의 자원 관리

- Airflow에서 DAG나 Task 실행 시, 자체 워커를 사용하는 대신 Kubernetes에 요청하여 필요한 사양의 서버를 빌려 실행하고, 작업이 끝나면 Return한다.

- 이 방식은 특정 역할에 국한되지 않고, 다양한 용도로 활용 가능한 공용 서버 클러스터를 기반으로 작동한다.

- 마스터 노드를 통해서 다양한 서비스들이 필요한 자원을 요청하고 그거를 받아서 마치 자기것 처럼 쓰고 끝나면 return한다.

 

Operator 수준에서의 Docker 및 Kubernetes 활용

- DAG는 여러 Task로 구성되고, Task는 Operator를 통해 실행

- 특정 Task를 다음과 같은 Operator로 구성하여 실행 환경 문제를 해결할 수 있다.

  • DockerOperator: Task를 Docker Image로 구성하고, Airflow Worker 위에서 Container를 실행. 전용된 분리 공간을 만들어줘 이를 통해 라이브러리 충돌 문제를 방지할 수 있다. 이 방식은 Task별로 독립된 실행 환경을 제공해주고 환경 충돌 문제가 발생한 일부 Task에만 적용할 수도 있다.
  • KubernetesPodOperator: Task 자체를 Docker Image로 만들어, 전용 Worker 노드가 아닌 Kubernetes 클러스터에서 서버를 받아 실행.

- DAG는 여전히 Airflow 전용 서버에서 실행되고 스케줄링되지만, Task는 Kubernetes 클러스터에서 자원을 할당받아 유연하게 실행된다.

Airflow Executor 활용

- Airflow Executor는 DAG에 포함된 Task를 관리하고 실행하는 역할을 수행한다.

- Executor의 종류에 따라 Task를 병렬, 순차로 실행할 것인지 정해진다.

- Kubernetes와 연동할 경우, Kubernetes Executor를 사용하여 Airflow가 Kubernetes 클러스터 상의 서버를 활용하도록 설정할 수 있다.

 

Docker란?

내 개발 환경에서는 잘 동작하던 프로그램이

외부 환경(test 환경, 또는 production 환경)에서는 제대로 실행되지 않는 경우가 많다.

① 라이브러리와 모듈의 충돌

② 설치해야 할 파일이나 설정이 누락된 경우

③ 운영 체제별 환경 변수나 설정 파일 차이로 인해 프로그램이 실패

 

솔루션이 여러가지 있는데 그 중 하나: Docker

내가 개발에 사용한 컴퓨터 환경을 그대로 패키징해 다른 사람에게 제공할 수 있다면, 그 사람도 마치 내가 개발한 환경 그대로 프로그램을 사용할 수 있을 것이다.

Docker Image

내가 만든 소프트웨어를 모든 의존 라이브러리와 함께 패키징한 것

  • Docker Image를 만드는 과정을 빌드(Build)라고 한다.
  • Docker Image는 실행 시 Docker 엔진 위에서 동작하며( 컨테이너가 사용하는 CPU, 메모리, 네트워크 등은 결국 Host OS에서 제공)
  • Docker 컨테이너는 필요에 따라 Host OS의 파일 시스템을 마운트하여 사용할 수 있다.
  • 이러한 구조는 Host OS나 다른 Docker 컨테이너와의 충돌을 방지한다.

개발자는 자신의 컴퓨터에서 프로그램 실행에 필요한 모든 소프트웨어와 환경 변수를 Docker Image로 만들 수 있다. 이렇게 만든 Docker Image는 다른 사람이 받아 사용할 때, 환경이 완전히 동일하지 않더라도 Docker Engine이 실행되는 환경이라면 Docker Container라는 분리된 공간에서 실행할 수 있다.

다만, 여기서도 약간의 호환성 문제(Compatibility Issue)가 있을 수 있다.

  • Docker Image를 만든 환경의 컴퓨터 아키텍처(예: AMD, ARM, x86)에 따라 다르게 동작할 수 있다.
  • 일반적으로 리눅스 기반으로 만든 Docker Image는 대부분의 컴퓨터에서 정상적으로 실행된다.

Host OS가 macOS인 경우, Docker는 실제로 경량화된 가상 머신(VM)을 사용하여 리눅스 커널을 제공한 후 그 위에서 컨테이너를 실행한다. 이는 macOS 자체가 리눅스 커널을 지원하지 않기 때문이다. 이로 인해 macOS에서 Docker를 실행하면 자원 소모가 상대적으로 더 크다. Docker로 만든 리눅스 기반 소프트웨어는 대부분의 리눅스 환경에서 동작한다. 하지만, Windows 애플리케이션은 리눅스 기반 Docker 컨테이너나 macOS에서 실행되는 컨테이너에서는 동작하지 않는다. Docker가 Host OS의 커널을 기반으로 하기 때문. 또한, Docker에서 GUI(그래픽 사용자 인터페이스) 애플리케이션을 실행하는 데는 제약이..

내가 만든 Docker Image를 다른 사람과 공유하려면 Docker Registry(예: Docker Hub)에 업로드하면 된다. 다른 사람들은 이를 Registry에서 다운로드하여 자신의 환경에서 사용할 수 있다. 다운로드한 Docker Image는 필요에 따라 자신의 컨테이너에서 실행할 수 있고 이 컨테이너는 로컬 환경이든 프로덕션 서버든 동일하게 작동한다.

Docker의 목표는 소프트웨어를 일관되게 빌드하고 실행하고 배포

Docker의 목표

Docker의 주요 목표는 소프트웨어를 일관되게 빌드(Build), 실행(Run), 배포(Deploy)하는 것!

  • Dockerfile 작성: 애플리케이션이 필요로 하는 소프트웨어 의존성과 환경 변수를 정의
  • Docker Image 생성: Dockerfile을 기반으로 빌드하여 Image를 만든다
  • Docker Container 실행: 생성한 Docker Image를 컨테이너 형태로 실행
  • Docker Registry 공유: 다른 사람들이 사용할 수 있도록 Registry에 올린다

일관되어있다!! Docker를 사용하면 개발 환경, 테스트 환경, 프로덕션 환경 모두에서 동일한 설정으로 애플리케이션을 실행할 수 있다!!

 

Docker VS VirtualMachines

Virtual Machine은 AWS의 EC2가 대표적이다. 가상 컴퓨가 있고 그 위해 다양한 virtual machine들이 존재하는 형태로 유지. 이 때 Docker Container랑 다른점은 Host 운영체제 위에 Hypervisor라는 VM을 생성하고 관리하는 소프트웨어가 있다.(VMWare, VirtualBox) 그 위에 다수의 virtual machine이.. 이때 각 virtual machine은 진짜 컴퓨터처럼 각 OS를 가지고 올라간다. 정말 컴퓨터 하드웨어를 추상화 해서 하드웨어 안에 또다른 하드웨어를 돌리는 형태..

-> 단점: VM은 자신만의 OS를 필요로 하기 때문에 OS가 꽁짜 OS가 아니면 돈을 내야한다. License 비용 문제

모든 컴퓨터는 OS가 있는경우 부팅하는데 시간이 걸린다. 그래서 시작할때 오래걸림 

OS위에 OS가 있기 때문에 자원을 많이 메모리 디스크 같은거 많이 사용함.

 

하지만 소프트웨어를 실행하기 위한 독립적이고 분리된 공간을 제공하고 다VM단에서 독립적으로 실해돰으로 충돌 이슈가 사라진다. 소프트웨어 호환성 측면에서는 진짜 컴퓨터를 쓰는 것 같다. 

 

Docker Container도 소프트웨어를 실행하기 위한 독립적인고 분리된 공간(단 Docker Engine위에 경량화된 형태로) 

자체 파일 시스템을 갖고 있다. (volue이라고 부름) 또한 자체 OS를 갖는것이 아닌 호스트 시스템의 OS를 사용하고 있기 때문에 빠르다. (OS를 부팅할 필요도 없고, 라이센스 비용X)

Docker는 client server arcitecture로 볼 수 있다. Container가 많은 기능을 Docker Engine에 의존하는 형태

Docker가 가지는 이러한 경량성 때문에(속도 빠름) 다수의 서비스들이 다수의 서버를 가지고 돌아가야 하는 현대 웹 서비스에 사용하기 좋다. 또한 분리된 공간을 제공하기 때문에 라이브러리나 모듈 충돌 없다 다시한번 

 

하지만 많은 Docker Container가 생기므로 이거를 어떻게 관리할것인지.. Container Ochestration Service 사용(Kubernetis)

 

Docker 프로그램 개발 프로세스 

Docker를 사용하여 소프트웨어를 패키징(빌드)하고, 이를 컨테이너로 실행하여 다른 사람들과 공유하는 과정을 알아보

 

1. 소프트웨어 선택

먼저 대상이 되는 소프트웨어를 선택해야된다.

  • 개별 프로세스로 실행할 경우: 소프트웨어가 각기 개별 프로세스로 돌아간다면 그 수만큼 따로 독립적인 컨테이너에를 돌려야한다. 그리고 각 소프트웨어마다 Docker 이미지를 만들어야 한다.
  • 하나의 컨테이너에서 실행할 경우: 여러 소프트웨어를 하나의 컨테이너에서 실행하고자 한다면, 이를 위한 하나의 Docker 이미지만 만들면 된다.

지금 돌리고 있는 소프트웨어들이 모두 하나의 이미지로 들어가서 하나의 컨테이너에서 돌아간다라고 가정하겠다.

 

2. Dockerization

대상을 삼은 소프트웨어을 Docker Image로 빌드하는 과정을 Dockerization이라고 한다. 

예를 들어 Airflow를 하나의 Continer에 실행하고 싶다. -> Airflow와 실행에 필요한 모든 소프트웨어를 Docker 이미지에 담아야한다. Airflow는 여러 서비스(웹 서버, 스케줄러, 데이터베이스 등)를 사용할 수 있는데, 이를 하나의 Docker 이미지에 포함시키려면 각 서비스의 설정을 모두 Dockerfile에 명시

 

Dockerfile: 소프트웨어를 Docker 이미지로 변환하는 과정과 그 방법을 정의하는 파일

 

  • 오픈소스 프로젝트에서 Dockerfile이 있다면, 해당 프로젝트를 하나의 Docker 이미지로 만드는 방법이 Docker 파일에 기술되어 있다는것.
  • Dockerfile을 사용하여 이미지를 만들기 위한 명령어는 docker build 이 명령어를 실행하면 Dockerfile에 정의된 내용에 따라 소프트웨어를 하나의 Docker 이미지로 빌드할 수 있다.

 

Docker 이미지 구성요소(Dockerfile에 기술)

① FROM

- Docker 이미지의 기본이 되는 소프트웨어를 지정

- 예를 들어, 리눅스 운영체제나 파이썬 등을 기반으로 시작할 수 있다. ex) FROM ubuntu 또는 FROM python:3.9

② 코드 복사

- 내가 작성한 코드를 Docker 이미지로 복사,  COPY 명령

③ RUN

- Docker 이미지 빌드 과정에서 소프트웨어를 설치하는 데 사용

- 우분투 기반 이미지에서 apt-get을 사용하여 필요한 소프트웨어를 설치할 수 있다.

- RUN apt-get update && apt-get install -y curl

④ 기본 파일 복사 (파일 시스템 스냅샷)

- 실행에 필요한 기본 파일들을 복사할 수 있다. 특정 파일이나 디렉터리가 Docker 이미지 내에서 필요한 경우

- Volume: 컨테이너가 자체 파일 시스템을 가지지만, 지속적인 파일 저장을 위해 외부 파일 시스템을 연결하는 개념

⑤ 환경 변수 설정 (ENV와 ARG)

- ENV: Docker 이미지가 실행될 때 필요한 환경 변수를 설정합니다.

- ARG: Docker 이미지 빌드 시에 필요한 환경 변수를 설정합니다.

 

 

⑥ ENTRYPOINT / CMD

- Docker 컨테이너에서 프로그램을 실행할 때 사용

⑦ 메타 데이터

- 이미지의 버전, 작성자, 설명, latest라는 태그가 기본 버전으로 사용

 

3. Docker 이미지 실행

docker run은 주어진 이미지를 처음 실행해서 컨테이너 안으로 띄우는거고 

docker exec은 이미 실행되어있는 container에 명령을 내리는 

 

Airflow를 실행하기 위한 복잡한 설정과 실행 명령들을 Dockerfile에 기록할 수 있지만, 설정이 복잡하다면 이를 shell script로 작성하여 Docker 이미지 내에서 실행하는 것이 일반적

 

4. 이미지 공유

DockerImage를 다른 사람이 실행해야한다하면 DockerRegistery인 DockerHub과 같은 Docker Registery에 올리는게 일반적. 이 만든 Image를 결국 Production 환경에서 실행되어야 한다면 나 혼자 가질 수는 없다. 어딘가에 등록해서 다른사람 받아서 사용해ㄷ야되는데 이것을 Docker Registry가 있다. 

보통 프로세스는 개발자가 본인의 개발 서버 컴퓨터에서 Docker Image를 만들고 Container에다 실행해서 Test해보고 돌아간다 싶으면 그거를 회사나 Cloud registry에 등록한다. 그럼 이거를 쓰고 싶은 사람은 image를 다운받아서 실행만 하면 된다. Docker pull을 사용해서
개발자가 소프트웨어를 개발하고 끝나면 Dockerization를 통해서 Docker image를 만들고 Docker Image를 test 환경에서 돌리고 이때 github과 연동이 많이 된다.(소스코드는 github에 있을 수 있기 때문에 gihub단에서 build process를 test를 돌고 소프트웨어를 Docker Image로 만드것들을 github과 docker이 공존하면서 연동하는 형태. test가 다 끝나고 아무 문제 없으면 그거를 외부 내부 registry에 로딩하고 그거를 production단에서 pull해서 서버에다가 실행한다.  이때 서버수가 몇개가 되느냐 Devops팀의 능력에 따라서 production cluster는 일반 서버를 쓸 수 있겠지만 쿠버네티스 cluster를 쓸 수 있다.

 

실습1

Node.js 서버 프로그램을 Docker 이미지로 빌드를 하고 실행해보는  Docker Hub에 등록하고 다른 서버에서 다운받아서 실행해보는 

 

간단한 HelloWorld를 print하는 프로그램을 Node로 만들어보고 Docker file을 만들어보고 그거를 바탕으로 Docker image로 만든다음에 Docker Container로 실행해보고 Docker Hub에 로딩하고 다른 컴퓨터(리눅스 서버)에서 pull을 해서 container를 실행해보는 전체 과정을 보도록 하겠습니다. 

그런데 app.js를 Node라는 command로 실행하려면 node환경이 설정 되어야한다. 그래서 그런 setting을 docker file에다 해준다. 이런 프로그램을 실행하려면 아무것도 없는 깡통 리눅스에서 이런 프로그램을 실행한다하면 

a. OS선택 (Linux)

b. Node 설치

c. app.js를 copy한다.

d. 그다음에 node app.js로 프로그램 실행해야한다. 

 

-> 이 내용을 Dockerfile에 기술하면 docker build command를 통해서 Docker Image 생성이 가능 

 

Docker File

Docker 에게 소프트웨어를 어떻게 설치하고 실행할지 기술해주는 그런 text 기반의 파일

 

1. FROM

- 먼저 베이스 이미지 지정

-  Docker registy에 연동되어있다는 전제하에서 그 registry에 있는 node:alpine이라는 이름의 이미지를 다운받아서 기본으로 쓰겠다는것.

- FROM다음에 오는것은 Docker image 이름이다. Docker Image 이름은 앞에 실제 이미지 이름이 있고 그다음에 버전이 나온다. 버전은 숫자일수도 string일 수도 있다. 

2. COPY

- image에 포함이 될 코드들을 복사해주는 역할을 한다. 

- . 을 쓰면은 현재 디렉토리에 있는 내용들이 모두 /app이라는 폴더 밑으로 copy된다. /app은 docker image에서 생성되는 폴더가 될것이고 이게 container안에서 생기는 폴더가 된다.

- Copy를 통해서 현재 디렉토리에 있는 내용들을 docker image상의 /app이라는 폴더로 copy. 그리고 그 폴더에 있는 파일 중 하나가 app.js 

3. WORKDIR

- 이제부터 실행하는 뒤의 모든 command들 작업 디렉토리를 지정

- /app으로 가정하겠다.  WORKDIR 이걸 안써주면 cmd를 쓸때 ./app을 다 써야된다. CMD node /app/app.js

4. CMD

- docker container가 시작 될 때 실행되어야하는 명령이 cmd로 들어온다. 

 

많은 키워드들이 있지만 그중에 일단 4개를 써서 

alpine이라는 경량 리눅스를 기반으로 한 node 런타임을 설치를 하고 현재 폴더에 있는 app.js라는 파일을 /app으로 copy하고 그리고 그 디렉토리 안에서 node app.js라는 command실행해주면서 docker container 생성되고 애플리케이션 실행된다.. 

그외에도 

1. ARG, ENV

- 리눅스 환경변수 세팅해주는 명령

- ENV는 Docker image가 만들어 질때만 쓰이는 것이 아닌 최종적으로 Docker Image에 저장되고 컨테이너 실행 시에도 사용 가능

- ARG 는 빌드 과정에만 사용되고 최종 이미지에 안들어간다. 

- ARG,ENV 둘다 docker image를 빌드할때 사용하지만 env에 정의된 환경변수만 Docker image에 남아서 최종적으로 contianer에서 실행될떄도 이용가능한 환경변수 된다.

2, USER

- 컨테이너 실행 시 사용할 리눅스 사용자 ID를 지정

- USER <사용자 ID 또는 이름>

3. EXPOSE

- 내가 실행하는 것이 웹서비스(데이터베이스같은 네트워크 서비스)라고 하면 어느 TCP port를 열어 줄거인지

- 예를 들어 MySQL은 expose해야되는 포트는 3306이 될것이다. EXPOSE 3306

4. RUN 

- image를 빌드할 때 실행할 command 지정

- devian이나 ubuntu 계열의 리눅스로  세팅하고 있다하면 apt-get을 통해 다양한 설치 작업

- ex) RUN apt-get update && apt-get install -y curl  -> curl이라는 모듈을 설치한다. 

- 내가 docker에서 실제로 image를 만들기 위해서 docker build라는 command를 실행할 때 docker run 뒤에 적어준 명령들이 하께 실행된다. 

5. CMD, ENTRYPOING

-둘다 container가 처음 시작될 때 어떤 명령 실행되어야되는지 적어주는 키워드이다. 

- 구체적으로 docker run image를 적어주는데 특정 docker image를 처음으로 container로 로딩해서 실행할 때, 그 때 어떠 명령을 실행할 것인지 CMD나 ENTRYPOINT에 적어줘야한다.

- 두개가 동시에 쓰일 수 도 있고 하지만 제일 좋은것은 ENTRYPOINT는 쓰지않고 CMD만 사용하는 것

두 경우 모두 image로 빌드하고 container로 실행해보면 실행되는 순간에 마지막만 command2.sh만 실행된다.

- 두개의 경우 마지막 지정된 것만 실행된다. 둘다 쓰이면 entrypoint가 우선순위 

- cmd는 overide할 수 있다. EntryPoint를 쓰는 겨경우는 CMD를 통해 파라미터를 지정해 줄 수 있다. 

cmd로 실행하면 덮어쓰기 가능. 뒤에 cmd2.sh명시해주면 cmd2.sh실행 기본은 cmd1.sh
entrypoint와 cmd 둘다 쓰면 entrypoint에 지정된 sh 실행, cmd에 지정된 값들이 ENTRYPOINT의 지정된 명령을 실행할 때 parameter로 들어간다. 새로운 인자 지정해 줄 수도 있다.

- cmd는 기본적으로 docker run 명령어를 쓸 때 덮어쓰기 가능하다. 혼자쓰면 그 자체가 명령어인거고 entrypoint하고 같이 쓰면 entrypoint에 지정된 명령의 parameter가 된다. 

- 복잡하니 최대한 CMD만 사용하자. ENTRYPOINT를 쓰면 편리한 경우가 몇몇 있다. 

 

남이 만든 AIRFLOW DOCKER FILE을 보자. ( puckel/docker-airflow: Docker Apache Airflow ) 

실제 Airflow를 설치해주는 Docker file의 내용

 

- ENV는 환경변수, build타임에도 사용되지만 최종적으로 image에 저장이 되어서 container가 실행이 될때도 이용가능한 환경변수가 된다. run command에서도 쓰이지만 cmd안에서도 cmd에서 실행해주는, entrypoint에서 실행해주는 script안에서도 env로 지정된 환경변수들은 이용가능하다.

- ARG는 빌드타임에만 실행되고 최종 image에는 저장안되는 환경변수

- COPY는 내가만든 코드들, 환경설정 파일들을 image안에다가 copy하는것 

- 빌드할때는 RUN 실행 AIRFLOW_USER_HOME 디렉토리에 주인을 airflow 유저로 바꾸고 있따. 

- 이 서비스는 세개의 TCP 포트를 열고 있따. 8080은 webserver가 나머지 두개는 ?

- 뒤에 나오는 모든 파일들은 기본 path을 AIRFLOW USER HOME으로 해라

- entrypoint명령을 실행하면서 cmd지정한 값이 파라미터로 붙을 것이다. 

-> Airflow 1.10.9를 설치해주는 Docker파일의 내용 

 

Docker Build

이제 Docker file이 만들어졌다면 이제 Image를 만들어야하는데 

이 때 사용할 수 있는것이 docker build라는 명령 

- docker build -t {이름} 을 준다. 태그 뒤에 이미지 이름 지정 . 만약 버전 같이 주고 싶으면 이름: 버전  아무것도 안주면 버전으로는 latest들어간다. 

- dcker build --platform linux/amd64 -t hello-world-docker . (뒤에 . 있다)

- 내가 만드는 이미지 이름은 hello-world-docker. hello-world-docker라고 하는 이미지가 지금 이 directroy에 있는 docekrfile을 가지고 만들어진다. (맨 뒤의 .이 필요한 이유 만약 다른 디렉토리에 있다면 . 대신 PATH 맞춰주면 된다. )

- --platform -> DOCKER는 완전히 OS간의 호환성을 보장해주지 못한다. 만약 M1 chip으로 만들어노트북으로 이미지 만들면 이 이미지들은 ARM 아키텍쳐 갖게 된다. 하지만 대부분의 리눅스 서버들은 amd 또는 x86 과 관계된 architecture를 가진다. build할 때 platform은 linux의 amd architecture를 하겠다!  

- image를 docker container로 실행하기 위해서는 docker run 명령어로 이미지 이름 지정하고 (버전 있으면 같이) 이 때 cmd에 지정되었던 기본 명령이 실행된다!

- 이 이미지를 다른 서버에서 다운받아서 사용하고 싶다면 docker hub같은 cloud registry에 등

 

dockuer hub

지금 까지 docker image를 docker file을 통해서 만들고 docker contianer로 실행해 보았다.

이제 이거를 docker hub에 repo로 등록하고 이거를 새로운 리눅스 서버에 가서 다운받은 다음에 거기서 docker container로 돌려봐야한다. 

 

먼저 docker tag라는 명령을 써서 현재 이미지의 이름을 keeyong/hello-world-docker로 바꿔줘야한다. 

첫번째 인자는 지금 존재하는 이미지의 이름(버전 포함해서) 두번째 인자는 새로운 이름 

$  docker image ls

$ docker tag hello-world-docker:latest keeyong/hello-world-docker:latest

$ docker image ls  -> 바꿔있는것 확인

$ docker login --username=keeyong -> account에 access 권한 있다는 증명 (패스워드를 별도 프롬프트에서 물어봄)

$ docker push keeyong/hello-world-docker  -> 내가 만든 이미지를 서버단에 올린다.

IMAGE ID가 정말 unique한 ID image의 이름은 REPOSITORY:TAG형식인데 첫번쨰와 2번쨰 결과의 image id가 같다. docker tag명령으로 별칭을 새로 주었었기 때문(이름을 바꾸는게 아님) 첫번째 주어진 인자에 두번째 인자의 별칭을 만들어 주는것, Docker Hub에서 다운받았는데 namespace정보 없으면 official 이미지

 

Docker Hub로 부터 받은 Image 실행

Play with Docker

꽁짜로 리눅스 서버를 4시간 동안 사용할 수 있는 서비스 (Docker가 설치됨)-> docker와 관련된 테스트를 하는데 사용

서비스에 로그인해서 docker image를 pull하고 docker container로 실행을 하고 Node application이 실행되는지 확인

(cmd 키워드에 node runtime사용해서 app.js실행되게 설정)

$ docker version 

$ docker pull keeyong/hello-world-docker -> 이미 docker hub에 로그인한 경우 이 서버는 

$ docker image ls

$ docker run keeyong/hello-world-docker  ->만약 로컬에 다운로드받은 이미지 없으면 알아서 pull해서 실행해주긴함

push, pull은 login이 되어있어야한다. build는 image만들기, t를 통해 이름과 버전 명시 가능, tag는 이미지에 별칭 주는것 . docker run, exec에 it붙여서 interactive하게 명령 내리기 가능

실제실습

Docker file

현재 디렉토리에 Dockerfile과 app.js가 있으며 cat과 ls를 통해 확인

Image Build 

build 할때 m1이면 patfor명시 안그러면 mac에서만 돌아감

Container run

docker tag 로 이름 바꾼후 docker hub에 push

똑같은 image id에 대해서 두개의 repository가 생긴다. push하기전에 login

docker pull로 docker hub에 있는 image 다운후 container실행

실습2

docker run ubuntu하고 docker ps하면 실행되는 container 안보인다. 사실은 conatiner 이미 실행됐는데 별 명령 안줘서 끝난것. 보통 docker ps를 하면 지금 떠있는 container들이 보인다. airflow만 보인다. 

docker ps -a 하면 실행이 끝난 것들도 보여준다. 그러면 ubunt image 실행되었던것 몇개 보인다. 

ubuntu를 그냥 실행하면 바로 끝나고 docker run-it ubuntu -> shell script를 사용해서 ubuntu docker conatiner 안으로 이동할 수 있다. root account로 들어갔다. 

apt 이용해서 install nano하면 nano 없다 나오는데 apt update를 해줘야 된다. 

그 후 install 하고 nano 실행 

실습3

먼저 적당한 폴더 만들고 터미널 들어가서 

다운로드 받은 image를 Docker container로 실행하려면 

docker run --name =mysql_container -> 우리가 실행한 container의 id 부여, 나중에 docker exec 같은 명령어 실행 할 때docker ps로 id찾는 과정 skip 할수도.. 

 

그다음에 터미널 새로열고

mysql server돌고 있다. root user로 로그인하려면 mysql 서버가 임시로 만들어 놓은 password를 읽어와야한다. 이것은 container안의 log로 남는다. docker logs라는 명령어로 container id 지정한후 container 안의 stdout, stderr로 나간 로그 메세지들을 읽어온다. 읽어오고나서 generated로 들어간 키워드가 들어간 line이 무엇이 있는지 

 

그다음에 docker exec -it으로 interactive하게 방금 실행한 container를 대상으로 mysql sh을 실행하고 root user로 로그인

'Data Engineer > 데브코스' 카테고리의 다른 글

데브코스 데이터 엔지니어링 WEEK10 WIL(3)  (0) 2024.12.17
데브코스 데이터 엔지니어링 WEEK10 WIL(2)  (0) 2024.11.19
데브코스 데이터 엔지니어링 WEEK10 WIL(1)  (0) 2024.11.19
데브코스 데이터 엔지니어링 WEEK8 WIL(2)  (0) 2024.11.19
데브코스 데이터 엔지니어링 WEEK8 WIL(1)  (0) 2024.11.07
'Data Engineer/데브코스' 카테고리의 다른 글
  • 데브코스 데이터 엔지니어링 WEEK10 WIL(3)
  • 데브코스 데이터 엔지니어링 WEEK10 WIL(2)
  • 데브코스 데이터 엔지니어링 WEEK10 WIL(1)
  • 데브코스 데이터 엔지니어링 WEEK8 WIL(2)
dev.di
dev.di
devdi 님의 블로그 입니다.
  • dev.di
    개발 블로그
    dev.di
  • 전체
    오늘
    어제
    • 분류 전체보기 (28)
      • Algorithm (9)
        • Basics (9)
      • AWS (0)
        • AWS (0)
        • SAA (0)
      • Computer Science (1)
        • OS 벼락치기 (1)
        • DB 벼락치기 (0)
      • Data Engineer (8)
        • Airflow (0)
        • Data Warehouse (0)
        • Kafka (0)
        • Spark (0)
        • 데브코스 (8)
      • Docker (0)
      • Interviews (1)
      • Network (2)
        • Physical Layer (0)
        • Data Link Layer (0)
      • OOP (3)
        • GoF (3)
      • Python (4)
        • Django (3)
        • Scraping (1)
      • Software Engineering (0)
      • Spring (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    데이터 웨어하우스
    포트포워딩
    IPv4
    sql
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
dev.di
데브코스 데이터 엔지니어링 WEEK11 WIL(1)
상단으로

티스토리툴바