데브코스에서 진행한 강의에 docker compose에 대한 자세한 내용을 작성해두었으니 참고하시면 좋을 것 같습니다.

이번 포스팅에서는 data engineering zoomcamp에서 진행한 간단한 docker compose 파일을 작성하는 과정을 다룹니다.

 

docker compose 파일 생성하기

우선 docker-compose.yml 파일을 생성하고 안에 다음과 같이 틀을 잡았다.

services:
  pgdatabase:
    image: postgres:13
    

  pgadmin:
    image: dpage/pgadmin4

 

우선 만들고자하는 컨테이너별로 이미지를 할당했다. database는 postgre:13으로, pgadmin은 pgadmin4를 사용!

 

컨테이너 정보 입력하기

컨테이너에서 필요로하는 기본 정보들을 입력한다.

  • environment: 각 컨테이너의 환경 변수들을 설정
  • volumes: 볼륨을 설정해준다. ":rw" 라는 새로운 값이 들어가있는데 read write 권한을 준다는 의미이다.
  • ports: 내부와 외부 포트를 맵핑해준다. 로컬에서 docker 내부의 해당 포트 접근이 가능해진다.
services:
  pgdatabase:
    image: postgres:13
    environment:
      - POSTGRES_USER=root
      - POSTGRES_PASSWORD=root
      - POSTGRES_DB=ny_taxi
    volumes:
      - "./ny_taxi_postgres_data:/var/lib/postgresql/data:rw" # read write
    ports:
      - "5432:5432"

  pgadmin:
    image: dpage/pgadmin4
    environment:
      - PGADMIN_DEFAULT_EMAIL=admin@admin.com
      - PGADMIN_DEFAULT_PASSWORD=root 
    ports:
      - "8080:80"

 

실행 & 결과

docker compose up 명령으로 실행해주면 다음과 같이 두개의 컨테이너가 올라온다.

 

네트워크 이름을 명시하지 않아도 둘은 같은 네트워크에 묶여있다!

 

pgAdmin에 접속하면 정상적으로 db에 연결된 것을 볼 수 있다.


전체 코드는 Github에 업로드 하였습니다.

https://github.com/poriz/data-engineering-zoomcamp-poriz/tree/main/01-docker-terraform/introduce_to_docker

'Infra & Container > Docker' 카테고리의 다른 글

Docker - Docker compose  (0) 2024.03.21
Docker - 명령어 정리 & Volume  (0) 2024.03.21
Docker - Postgres > Data Ingestion  (0) 2024.03.21
Docker - Postgres > pgadmin  (0) 2024.03.20
Docker - Postgres  (0) 2024.03.20

Docker Compose란?

: 다수의 Container가 소프트웨어로 구성되는 경우에 사용가능한 툴과 설정파일 모음

  • docker-compose.yml이나 docker-compose.yaml 파일로 환경설정을 수행한다.
  • Docker Desktop의 일부로 설치된다.
  • docker-compose —version으로 버전확인

docker-compose.yml 작성

: v2와 v3가 합쳐진 버전 사용 → 1.27 버전 이후 docker 명령으로 compose가 추가되었다.

  • services : 프로그램을 구성하는 서비스들을 지정
    • 각 서비스는 별개의 image 지정과 container 실행으로 구성된다.
    • 각 서비스는 자신의 Dockerfile을 갖고 있어야한다.
    • 서비스 별 포트번호, 환경변수, 디스크 볼륨등을 지정해야한다.
  • volumes : 사용된 docker volume들을 지정
  • networks: 사용된 networks 지정

예시

services:
	frontend:
		build: ./frontend
		ports:
			- 3000:3000
	backend:
		build: ./backend
		ports:
			- 3001:3001
		environment:
			DB_URL: mongodb://database/vidly
	database:
		image: mongo:4.0-xenial
		ports:
			-27017:27017
		volumes:
			-vidly: /data/db
	volumes:
		vidly:

docker-compose 관련 명령어 정리

  • docker-compose build : build 키로 지정된 것들 대상을 build
  • docker-compose pull : docker-hub에서 이미지를 읽어오려고 한다.
  • docker-compose images : docker-compose로 실행된 컨테이너들 대상으로 이미지를 보여준다.
  • docker-compose push : docker-hub로 푸시
  • docker-compose up, down, stop, rm : 실행, 종료, 중지, 삭제
    • docker-compose up : build→ create → start 순서
  • docker-compose ps : 프로세스를 보여준다.
  • docker compose 로 사용해도 된다.
  • 빌드 시 yml파일을 직접 입력하고 싶은 경우 : docker-compose -f compose_file.yml build

docker-compose networking

: docker들끼리 네트워크 연결이 필요한 경우

  • service에 준 이름으로 호스트 이름이 생성된다, 내부에 DNS서버가 생성되어 이름을 내부 IP로 변환해준다.
  • docker network ls

Voting application을 docker-compose로 실행

5개의 컨테이너를 일일히 실행했을 때의 문제점

  • postgres 실행이 정상적으로 동작하지 않았다.

이 문제 해결을 위해 Container 실행 시 2개의 환경변수를 넘겨주어야한다.

  • POSTGRES_USER: “postgres”
  • POSTGRES_PASSWORD: “postgres”
  • docker-compose.yml을 통해 환경설정을 넘겨준다.

docker-compose.yml로 포팅하기

# docker-compose.yml 간단한 버전
services:
	redis:
		image: redis:alpine
	db:
		imgae: postgres:15-alpine
	vote:
		image: ./vote
		ports:
			-5001:80
	result:
		build: ./result  # dockerfile의 위치, build위치.
		ports:
			-5002:80
	worker:
		build: ./worker

실습 수행

  • docker compose -f docker-compose.mac.yml up
  • 결과
  • down : yml을 명시하지않고 down하게되면 network가 유지된다.

: 따라서 다음과 같이 docker-compose -f compose_name.yml down 을 사용한다.

docker-compose.yml 개선하기

networks 정의하기

: networks를 지정하지않으면 호스트 이름으로 하나의 네트웤이 형성된다. 이를 분리해본다.

networks:
	back-tier: (redis,worker,db,vote,result)
	front-tier: (vote,result)
  • frontend도 back에 접근해야하기 때문에 back-tier에 연결해준다.
  • 모든 서비스에 네트워크 키를 설정해준다.
# docker-compose.yml network-upgrade
services:
	redis:
		image: redis:alpine
		netwokrs:
			-back-tier
	db:
		imgae: postgres:15-alpine
		netwokrs:
			-back-tier
	vote:
		image: ./vote
		ports:
			-5001:80
		netwokrs:
			-back-tier
			-front-tier
	result:
		build: ./result  # dockerfile의 위치, build위치.
		ports:
			-5002:80
		netwokrs:
			-back-tier
			-front-tier

	worker:
		build: ./worker
		netwokrs:
			-back-tier

volumes 정의

: db의 내용이 유지되어야하기 때문에 볼륨을 지정해준다.

services:
	...
	db:
		volumes:
		- db-data:/var/lib/postgresql/data
	...

command & entrypoint

  • command : 이미지 Dockerfile의 CMD를 덮어쓴다.
  • entrypoint: 이미지 Dockerfile의 ENTRYPOINT를 덮어쓴다.

healthcheck

: 컨테이너가 정상적으로 동작하는지 체크한다. Dockerfile에서 기술 가능하며, docker-compose에서 덮어쓰기가 가능하다. volumes로 지정해주면 정보 유지가 가능하다.

예제 코드

healthcheck:
	test: ["CMD","curl","-f","http://localhost"]
	interval: 1m30s
	...

depends_on

: 서비스의 의존성 체크. 먼저 실행되어야하는 서비스들을 기술한다.

  • short form
depends_on:
	-db
	-redis
  • long form
depends_on:
	db:
		condition: service_healthy
	redis:
		condition: service_started
  • condition의 종류
    • service_started
    • service_healthy
    • service_completed_successfully: 해당 컨테니어가 성공한 후에 작동

environment

: 컨테이너 안에서 실행될 때 환경변수들을 지정 (ENV)

  • Map 문법
environment:
	RACK_ENV: development
	SHOW: "true"
		USER_INPUT:
  • Array 문법
environment:
	- RACK_ENV: development
	- SHOW: "true"
		- USER_INPUT:

최종 파일 : https://github.com/learndataeng/example-voting-app/blob/main/docker-compose.yml

Docker 명령 정리

  • image
    • 빌드 명령 : docker build —platform=linux/amd64 -t tag_name
    • 이미지 확인 : docker images
    • 이미지 삭제 : docker rmi 또는 docker image rm
  • Docker Hub
    • 로그인 : docker login -u userID -p PW
    • Pull : docker pull accountID/image_name
    • Push : docker push accountID/image_name
  • Container
    • 생성 : docker create
    • 이미지 실행 : docker run —name -p -v image_name
    • 프로세스 확인 : docker ps
    • 컨테이너 실행 : docker start container_id
    • 컨테이너 정지 : docker kill
    • 컨테이너 삭제 : docker rm
    • 로그 확인 : docker logs -f container_id (—tail 옵션사용가능)
    • 이미 실행된 컨테이너에게 명령 수행 : docker exec container_id <명령어>
    • 백그라운드에서 수행 : docker run -d image_name

Docker Volume

: Docker Container가 실행되었다가 중단되면 데이터가 사라진다. → 데이터의 유지를 원한다면 Volume이 필요하다.

정의

  • 호스트 파일 시스템 폴더를 Docker Container 파일 시스템의 폴더로 마운트하는 것
    • Container가 사라져도 데이터를 남게한다.
    • 마운트 : 물리적 장치를 파일 시스템의 특정 폴더에 연결하는 것

Docker Volume 타입

: docker run -v를 실행할 때 지정된다.

  1. Host Volumns : 페어로 지정
    • docker run -v host_file_sys_path:container_file_sys_path
  2. Anonymous Volumes : 컨테이너 패스만 지정
    • dockr run -v path
    • Dockerfile에서 사용되는 방식, 호스트에 액세스되지는 않으나 재시작 시 유지
  3. Named Volumes : docker run -v : 이름과 컨테이너 패스를 지정
    • docker run -v name:path
    • 가장 선호되는 방식, 하나의 Volume을 다수의 컨테이너에서 공유 가능
    • docker-compose에서도 사용된다.
  • Readonly로 지정 : name:path:ro

Dockerfile에서 volume 사용 예

  • nginx 데모#1 (저장 안됨)
    • docker run -d —name=nginx -p 8081:80 nginx (8081포트로 열기)
    • container 접속 : docker exec —user=root -it nginx sh
      • nano 설치 (apt)
      • nano /usr/share/nginx/html/index.html 내용 편집
    • docker 재시작 (docker restart nginx)
  • nginx 데모#2 (Volume 사용)
    • 맵핑을 위한 폴더와 파일 생성 (index.html)
    • Dockerfile로 이미지 빌딩
      FROM nginx:latest
      RUN echo "<h1>test volume</h1>" > /user/share/nginx/html/index.html
    • 폴더 마운트
      • docker run -p 8081:80 —name nginx -v local_path:/usr/share/nginx/html nginx
  • docker-compose.yml (airflow의 내용으로 사용)
    volumes:
    - ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags

Docker Volume 명령들

  • Volume 확인 : docker volume ls
  • 삭제 : docker volume rm
  • 사용되지 않는 모든 볼륨 삭제 : docker volume prune
  • 특정 볼륨의 내용을 깊게 살펴보고 싶은 경우 : docker volume inspect

'Infra & Container > Docker' 카테고리의 다른 글

Docker - 간단한 docker compose 만들어보기(zoomcamp)  (0) 2024.03.21
Docker - Docker compose  (0) 2024.03.21
Docker - Postgres > Data Ingestion  (0) 2024.03.21
Docker - Postgres > pgadmin  (0) 2024.03.20
Docker - Postgres  (0) 2024.03.20

Data Ingestion: 데이터 수집, 데이터를 추출하여 다른 소스로 로드하는 행위라고 한다.

 

Data ingestion하는 과정을 실습해본다. 그 전에 꿀팁을 하나 가져왔다.

주피터 노트북으로 만든 ipynb 파일을 python script로 변경해주는 방법이다! (나만 몰랐을 수도..?)

Jupyter nbconvert —to=script file_name.ipynb

 

다음 코드를 사용하면 file_name.py로 변환되어 파일이 생성된다. 그러나 주의할점이 하나 있다.

주석으로 실행순서등이 따라오기 때문에 한번정도는 주석제거를해서 코드를 보기 좋게 만드는 작업이 권장된다.


수집용 파이썬 코드 생성하기

argparse를 사용해서 인자 받기.

python에서 argument를 받아서 사용하기 위해 내장 라이브러리인 argparse를 사용하였다.

parser를 설정해주고, 내가 원하는 인자들을 입력해주면된다.

parser = argparse.ArgumentParser(description='Ingest parquet to postgres') 

# user, password, host, port, database name, table_name, url
parser.add_argument('--user', help='user name for postgres')
parser.add_argument('--password', help='password for postfres')
...
parser.add_argument('--url', help='url of the parquet file')

args = parser.parse_args()

 

마지막으로 args에 parser들을 담아서 함수에 넣어 사용하면 끝!

 

함수 변경 해주기

지난 실습에서 사용한 코드를 받아와 약간의 수정을 진행했다.

ef main(params):
    user = params.user
    password = params.password
	...
    url = params.url

	...
    engine = create_engine(f'postgresql://{user}:{password}@{host}:{port}/{db}')

Docker 이미지 생성 & 실행

Dockerfile

이미지 생성 전에 파이썬을 사용하면서 설치했던 추가 라이브러리들을 같이 적용시켜야한다.

따라서 Dockerfile을 수정해준다!

FROM python:3.9

RUN apt-get install wget
RUN pip install pandas sqlalchemy psycopg2 pyarrow

WORKDIR /app
COPY ingest_data.py ingest_data.py

ENTRYPOINT ["python", "ingest_data.py"]

 

wget을 설치해주고, sqlalchemy, psycopg2, pyarrow 라이브러리도 같이 설치해주었다.

그리고 사용할 파이썬 파일을 copy해준 후에, ENTRYPOINT(시작 시 실행)에도 넣어주었다.

 

Image build & run

이미지 빌드는 다음 코드로 진행했다. 가벼운(?) 빌드 코드이다.

docker build -t taxi_ingest:v001 .

 

이제 docker run을 해줘야하는데 신경써야할 부분이 많다.

우선 우리의 수집용 파이썬 코드가 어떻게 동작하는지 다시 본다..

  1. wget을 이용해서 parquet 데이터를 받아오기
  2. sqlalchemy를 사용해서 postgres와 연결
  3. postgres에 데이터 전송하기

그렇다면 우리가 실행시킬 이 이미지는 postgres와 동일한 네트워크에 있어야한다!

docker run -it --network=pg-network \
    taxi_ingest:v001 \
        --user=root \
        --password=root \
        --host=pg-database \
        --port=5432 \
        --db=ny_taxi \
        --table_name=yellow_taxi_trips \
        --url='https://d37ci6vzurychx.cloudfront.net/trip-data/yellow_tripdata_2023-01.parquet'

 

host의 경우에도 postgres db를 연결해주면 완성이다.

이제 실행시켜주면 다음과 같은 결과를 볼 수 있다.

 


전체 코드는 Github에 업로드 하였습니다.

https://github.com/poriz/data-engineering-zoomcamp-poriz/tree/main/01-docker-terraform/introduce_to_docker

'Infra & Container > Docker' 카테고리의 다른 글

Docker - Docker compose  (0) 2024.03.21
Docker - 명령어 정리 & Volume  (0) 2024.03.21
Docker - Postgres > pgadmin  (0) 2024.03.20
Docker - Postgres  (0) 2024.03.20
Docker - Introduction to Docker  (0) 2024.03.18

+ Recent posts