Docker Compose
주요 메모 사항
Docker 명령 정리
Image 관련
- 빌드명령어, 아키텍처를 --platform 옵션으로 설정
docker build --platform=linux/amd64 -t name/hangman
- 목록
docker images
docker image ls
- 이미지 삭제
docker rmi
docker image rm
Docker Hub 관련
- git과 같은 명령
docker login -u 사용자ID -p 사용자PW
docker pull name/hangman
docker push name/hangman
Container 관련
- 리눅스명령어와 거의 동일하다
docker create
docker run --name -p -v 이미지이름
docker ps
docker ps -a
docker ps -q
docker stop 컨테이너이름 (혹은 컨테이너ID)
docker start 컨테이너이름 (혹은 컨테이너ID)
docker restart 컨테이너이름 (혹은 컨테이너ID)
docker kill 컨테이너이름 (혹은 컨테이너ID)
docker pause 컨테이너이름 (혹은 컨테이너ID)
docker unpause 컨테이너이름 (혹은 컨테이너ID)
docker rm 컨테이너이름 (혹은 컨테이너ID)
Container logs
- 로그 확인, tail로 마지막 100개, 뭔가 느낌이 head 옵션도 있을 것 같음
docker logs -f 컨테이너이름 (혹은 컨테이너ID)
docker logs --tail 100 컨테이너이름 (혹은 컨테이너ID)
exec
- 실행
docker run --name=hangman name/hangman
docker exec hangman cat /etc/hosts
Container detach & attach
- -d 옵션은 실행이 끝나도 컨테이너를 멈추지 않겠다는 것임!, attach는 background가 아닌 foreground
docker run name/hangman
docker run -d name/hangman -> a123d45*********
docker attach a123
Docker Container의 일생 Life Cycle
Docker Volume이란?
Docker Container가 무슨 이유로건 중단되고 재실행된다면 그전의 데이터는 어떻게 되는 걸까?
Docker Volume의 필요성
특정 소프트웨어가 Docker Container를 통해 일회성으로 동작하는 것이 아니라 계속해서 동작해야 한다면 데이터가 영구적으로 보관되어야함
ㄴ 예) 데이터베이스가 Docker Container안에서 동작한다면?
-> 이를 보장하는 기능이 Docker Volumes => Data Persistence, 여러가지 방법이 존재함
우리가 진행할 방법은?
ㄴ Docker Container내의 가상 파일 시스템과 호스트 시스템의 파일 시스템을 맵핑
ㄴ 예) 호스트 파일 시스템의 /home/keeyong/logs를 Docker Container의 /var/lib/airflow/logs로 맵핑
ㄴ 이 경우 Docker Container가 중단되더라도 모든 Airflow logs는 기록이 남게 됨
Docker Volume 예
Container와 Host 시스템이 특정 폴더를 공유
ㄴ Container가 사라지더라도 데이터는 남게 하는 것!
Container로 MySQL을 실행하는 경우 데이터가 저장되는 공간을 Docker Volume으로 설정
Docker Volume 정의
호스트 파일 시스템 폴더를 Docker Container 파일 시스템의 폴더로 마운트하는 것
ㄴ 호스트쪽에서 내용을 바꾸면 바로 Docker Container쪽에도 반영됨
ㄴ 반대도 사실이지만 Volume의 속성을 잡기 나름임 (예를 들면 읽기 전용)
ㄴ 이를 통해 Docker Container의 상태와 관계없이 데이터를 영구적으로 보관
파일 시스템에서 마운트란?
ㄴ 원래 마운트란 디스크와 같은 물리적인 장치를 파일 시스템의 특정 위치(폴더)에 연결해주는 것을 말함
ㄴ 예를 들어 윈도우에서 USB를 꼽으면 내 컴퓨터에 새로운 :D 혹은 :E와 같은 식으로 새로운 폴더가 생기는 것이 바로 마운트임
Docker Volume 타입
1. Host Volumes: docker run -v를 실행할 때 페어로 지정
ㄴ docker run -v /home/user/logs:/var/lib/airflow/logs
ㄴ 호스트 파일 시스템 PATH : 컨테이너 파일 시스템 PATH
2. Anonymous Volumes: docker run -v를 실행할 때 컨테이너 패스만 지정, docker한테 맡기는, 잘 안씀
ㄴ docker run -v /var/lib/mysql/data
ㄴ 이 방식이 Dockerfile에서 사용되는 방식으로 호스트쪽에 액세스되지는 않지만 재시작해도 유지됨
3. Named Volumes: docker run -v를 실행할 때 이름과 컨테이너 패스를 지정
ㄴ docker run -v name:/var/lib/mysql/data
ㄴ 가장 선호되는 방식. 이 방식이 하나의 Volume을 다수의 컨테이너에서 공유하는 것도 가능하게 해줌
ㄴ 이 포맷으로 뒤에서 살펴볼 docker-compose에서도 사용!
Volume을 Readonly로 지정하고 싶다면? -> ro
ㄴ name:/var/lib/mysql/data:ro
이미지 생성시 Docker Volume 사용법
1. Dockerfile, 디테일하게 다루지는 않을
ㄴ VOLUME 명령을 통해 anonymous volume만 지정 가능 (맥스님도 이유는 모르겠다고 하심)
2. docker-compose, 과정에서는 이 방법을 채택
ㄴ Host Volume이나 Named Volume을 사용하는 것이 일반적
Docker Volume 명령들
docker volume ls
docker volume rm
docker volume prune -> 사용하지 않는 모든 볼륨을 삭제하는 명령어
docker volume inspect -> 특정 볼륨의 내용을 더 보기 위함
Docker Volume을 Dockerfile에서 사용한 예
nginx를 실행
nginx란? -> 경량화된 웹서버, 여러개의 사이트를 연결시키는 Load Balancer 처럼 쓰임
해당 이미지의 쉘로 들어가서 html 파일을 수정해보고 이미지를 다시 실행해보자
restart 하고 다시 확인해보자, 다시 원상복구가 되어있음
Issue, 근데 restart 명령어로 컨테이너가 다시 동작하는게 아닌 것 같음 -> 필자는 kill 하고 다시 run 했음
MAX님은 $ docker rm nginx 로 아예 이미지를 삭제하고 다시 run 했음!
Host Volumes -v 옵션을 사용해서 진행
2개의 html 파일을 만들고 이를 host volume 위치로 지정할 예정
여기에서 host volume의 test.html을 변경해보자
바로 변경되어 있는 것을 확인할 수 있음
다시 처음부터 진행해보자, 삭제하고 run
당연히 계속 남아있음, host volume에 남아있기 때문
Docker Volume을 docker-compose.yml에서 사용한 예
Airflow 예)
volumes
ㄴ ${AIRFLOW_PROJ_DIR:-.}/dags:/opt/airflow/dags
ㄴ ${AIRFLOW_PROJ_DIR:-.}/logs:/opt/airflow/logs
ㄴ ${AIRFLOW_PROJ_DIR:-.}/plugins:/opt/airflow/plugins
데모를 진행하기 어려움이 있었음 (docker-compose를 배우지 않았음)
MAX님은 이미 docker위에 Airflow를 run중이셨는데 해당 과정이 나와있지는 않았음, 뒤에서 다루신다고 하심
host os의 airflow dags와 docker volume의 airflow dags가 마운트되고 있다는 것을 보여주심
다수의 Container로 구성된 소프트웨어 앞서 만들어본 Hangman 실행
다수의 컨테이너들이 유기적으로 돌아가야 하는 예시임
팁: Docker 환경 클린업 - CLI - 필자의 환경
Docker Desktop에서 모든 삭제하는 것이 가장 직관적
ㄴ Image를 삭제하려면 먼저 실행 중인 Container가 없어야함
ㄴ 따라서 맞는 순서는 먼저 Container를 중단하고 다음으로 Image를 삭제
컨테이너 삭제
ㄴ 원래는 docker container ls를 하고 Container ID를 개별적으로 docker container rm 뒤에 추가해야함
ㄴ 하지만 한번에 이를 실행하는 것이 더 좋음 -> $ docker container rm -f $(docker container ls -aq)
ㄴ (docker container ls -aq 로 컨테이너ID만 출력하는 것)
이미지 삭제
ㄴ 원래는 docker image ls를 하고 Image ID를 개별적으로 docker image rm 뒤에 추가해야함
ㄴ 하지만 한번에 이를 실행하는 것이 더 좋음 -> $ docker image rm -f $(docker image ls -q)
ㄴ (ls -q 도 같은 컨테이너와 맥락)
정말 다 삭제되었는지 확인
ㄴdocker ps
ㄴ docker images
팁: Docker 환경 클린업 (2) - Desktop에서 Troubleshoot 메뉴
그냥 클릭으로 삭제된다
voting application을 매뉴얼하게 실행해보기
https://github.com/dockersamples/example-voting-app
Docker에서 제공해주는 예제 프로그램임!
아래 이미지와 같은 방식으로 5개의 컨테이너가 실행되는 것
$ git clone https://github.com/dockersamples/example-voting-app
파일 구조, vote result worker을 빌드해야 한다
redis와 postgres는 공식 이미지들이라 빌드할 필요가 없음!
vote 빌드
result 빌드
worker 빌드
docker images
만약 5개의 이미지(redis, post gres)를 run 한다면?
ㄴ> 각각의 컨테이너로 실행은 되겠지만 서로 연동되어 있지 않음.
ㄴ> 그렇다면 각 컴포넌트 간의 네트워크 연결을 해야함
vote/app.py
vote container에 들어가서 inutils-ping 설치 후 ping 명령으로 redis 호스트 이름이 연결되는지 확인
result/server.js (강의에서는 진행 X)
$ docker run -d -e POSTGRES_PASSWORD=postgres --name=db postgres
명령어를 사용해서 실행시킬 때 PASSWORD를 지정안해주면 오류가 난다!
Postgres 연결시 postgres:postgres를 사용하고 있음을 주의깊게 볼 것
worker/Program.cs
Network 이슈 해결
docker의 network 기능 사용
ㄴ 과거에는 docker run의 link 옵션이 존재해서 해당 옵션을 사용했음
network을 하나 만들고 모든 컨테이너들을 이 네트워크 안으로 지정
ㄴ 연결 상황에 따라 별개의 네트워크를 만들고 사용도 가능함
ㄴ back-tier (redis, postgre, worker)
ㄴ front-tier (vote, result)
ㄴ 이번 매뉴얼 예제에서는 mynetwork을 하나 만들고 진행 예정
이번에는 mynetwork로 한번에 테스트 하지만 실제로는 Worker이 result-app이나 voting-app을 알 필요는 없다는 것은 알고 지나가야함!
제대로 연결, 사용할 명령어들
$ docker container rm -f $(docker container ls -aq)
$ docker network create mynetwork
$ docker run -d --name=redis --network mynetwork redis
$ docker run -d --name=db -e POSTGRES_PASSWORD=password --network mynetwork postgres
$ docker run -d --name=vote -p 5001:80 --network mynetwork vote
$ docker run -d --name=result -p 5002:80 --network mynetwork result
$ docker run -d --name=worker --network mynetwork worker
컨테이너를 모두 Clean Up
네트워크를 하나 만듬
네트워크 그룹? 에 포함시켜서 이미지들 run
localhost:5001 에서 확인해보자
그렇다면 vote와 redis가 연결된 것을 확인해보자
vote 컨테이너에 sh로 진입
redis에 ping 리턴이 성공
이러한 과정을 더 편리하게 사용하는 것이 docker-compose를 사용하는것!
내일 강의에서 다루신다고 한다.
공부하며 어려웠던 내용
'프로그래머스 데브코스-데이터 엔지니어 > TIL(Today I Learned)' 카테고리의 다른 글
06/15 50일차 개발환경 구축을 위한 Docker & K8s (5) (0) | 2023.06.16 |
---|---|
06/15 49일차 개발환경 구축을 위한 Docker & K8s (4) (0) | 2023.06.15 |
06/13 47일차 개발환경 구축을 위한 Docker & K8s (2) (0) | 2023.06.13 |
06/12 46일차 개발환경 구축을 위한 Docker & K8s (1) (0) | 2023.06.12 |
06/09 45일차 데이터 파이프라인과 Airflow (5) (0) | 2023.06.09 |