🔊 해당 포스팅은 이고잉님의 생활코딩 오픈튜토리얼의 Docker 입문 수업을 듣고 제 개인적으로 정리하는 목적하에 작성되는 포스팅입니다. 보다 자세한 강의는 여기를 참고해주세요.
이고잉님께서 다시 도커 강의를 제작하신 걸 보고 바로 들으러 갔다! 이번 포스팅에서는 Docker Compose 관련 명령어에 대해 알아보자.
새로운 무엇인가를 배울 때는 항상 그 새로운 무엇인가가 왜 등장했는지를 생각해 보면 이해가 더 수월한 것 같다. 도커 Compose 명령어는 그렇다면 왜 등장했을까? 우선 아래와 같이 컨테이너를 만드는 도커 명령어가 있다고 가정해보자.(해당 명령어의 원본은 이고잉님의 Github 계정인 여기에 있음을 필히 알립니다!)
위 사진은 2개의 컨테이너를 만드는 명령어인데, 딱 봐도 엄청나게 복잡해 보인다.. 위와 같은 2개의 도커 명령어를 하나의 파일로 만들어서 수행할 수 있다면 얼마나 좋을까? 그걸 가능하게 하는 것인 Compose 관련 명령어인데, 이 명령어를 입력시키기 전에 우리는 하나의 약속된 파일인 YAML 형태의 파일인 docker-compose.yml 파일에 위 2개의 복잡한 명령어를 정리해서 넣어주어야 한다.(이 docker-compose.yml 파일 형식은 저번에 배웠던 Dokcerfile 처럼 일종의 약속된 파일 형태이므로 이름이나 확장자를 변경해선 안 된다)
위 사진의 복잡한 명령어들을 하나의 docker-compose.yml 파일로 정리하려면 우선은 위 2개의 복잡한 명령어들이 어떤 컨테이너들을 만들려고 하는지 일종의 시나리오(?)를 파악해야 한다.
현재 우리는 워드프레스 컨테이너를 하나 만들고 MySQL 컨테이너를 하나 만들어서 워드프레스 웹서버를 오픈해 우리 웹 브라우저에서 컨테이너로 만든 워드프레스에 접근하려고 한다. 이 때 MySQL 컨테이너를 만드는 이유는 워드프레스가 MySQL을 주로 데이터베이스로 사용하기 때문이다. 어쨌거나 우리는 본질적으로 만드려는 컨테이너는 워드프레스 1개, MySQL 1개이다.
이제 아래 그림의 왼쪽에서 오른쪽으로 우리가 원하는 docker-compose.yml 형태로 명령어를 정리 및 요약해보자.
이제 yml 파일 기준으로 라인 하나하나씩 뜯어보면서 이해해보자.
1. version: , services:
먼저 오른쪽 yml 파일의 상단인 version 지시어는 해당 docker-compose의 스키마 버전을 먼저 명시해주어야 한다. 스키마 버전에 대한 자세한 설명은 여기를 참고하자. 그리고 다음의 services 지시어는 services 지시어 내부 영역에서 만들어줄 컨테이너들을 명시해줄 수 있다. 즉, 왼쪽 shell 에서 docker run 과 같이 컨테이너를 만드는 역할을 하는 셈이라고 생각하면 된다.
2. db: , app:
다음은 yml 파일의 db: , app: 이라고 되어 있는 부분이다. 눈치 빠르신 분들은 shell 파일에서 db, app 이 적혀있는 명령어를 재빨리 보셨을 듯 하다. shell에서 db, app은 바로 만들 컨테이너의 이름이다. 따라서 yml 파일에서 만들 컨테이너의 이름들을 db:, app: 이런식으로 정의해준다.
3. image:
다음은 image: 지시어이다. 이는 말 그대로 pull할 이미지를 의미한다.
4. volumes:
다음은 volumes 지시어인데, 이는 우리가 저번 포스팅에서 배웠던 Host의 파일시스템과 새롭게 만든 컨테이너의 파일 시스템과 연결할 때 사용하는 도커 명령어중 -v로 주었던 그것의 v이다. 왼쪽 shell에서 -v 관련 명령어를 살펴보면 알 수 있다. 사용방법은 shell 명령어와 매우 비슷하다. 즉, [Host의 파일시스템 경로]:[컨테이너 파일시스템 경로] 이런식으로 정의해주면 된다.
이 때, db 컨테이너에서 Host의 db_data 라는 폴더를 컨테이너의 /var/lib/mysql 폴더랑 연결하는데, 이렇게 하는 이유는 워드프레스로 사용자가 접근해서 적재되는 데이터들이 db 컨테이너 내부의 /var/lib/mysql 폴더에 적재가 될텐데, 만약 해당 db 컨테이너를 끄게 된다면 해당 /var/lib/mysql 폴더에 있던 데이터가 모두 날아가기 때문이다. 따라서 데이터를 따로 보관하기 위해서 Host 파일시스템의 db_data 라는 폴더와 연결시켜 동시에 보관하기로 한다. 이는 app 컨테이너에서 volumes: 지시어의 디렉토리도 마찬가지이다. 이렇게 하면 Host에서 HTML 파일을 수정하게 되면 app 컨테이너의 HTML 파일도 같이 수정되는 동기화가 가능해진다.
5. depends_on:
위 yml 파일을 보면 특이하게 app 컨테이너에만 depends_on 지시어가 존재한다. 우선 이를 이해하기 위해서는 워드프레스 서버는 MySQL 서버가 먼저 존재해야 한다. 그래야 워드프레스 서버에서 MySQL 서버에 있는 데이터를 가져올 수 있기 때문이다. 따라서 컨테이너를 만드는 순서 상 MySQL 컨테이너가 먼저 만들어져야 한다. 왼쪽의 shell에서는 애초에 명령어 순서가 MySQL 컨테이너인 db 컨테이너를 먼저 만들고 이후에 또 한 번의 docker run 명령어로 워드 프레스 컨테이너인 app 컨테이너를 만든다. 따라서 별도의 명령어를 입력할 때, 입력하는 순서만 잘 지정해주면 상관 없다. 하지만 yml 파일은 하나의 파일로 존재하므로 명확하게 어떤 컨테이너를 먼저 만들지 명시해주어야 한다. 따라서 depends_on 지시어를 사용하는데, 위에서는 워드 프레스 컨테이너가 MySQL 컨테이너 이후에 만들어져야 하므로 app 컨테이너에서 db 컨테이너에 '의존하고 있다'고 명시해주어야 한다.
6. environment:
이것은 그야말로 환경변수에 대한 설정이다. yml파일의 db: 영역을 보자. 우리가 MySQL DB에 접속하려면 접근하려는 ID, PW, 그리고 데이터베이스 이름 등에 대한 명시가 필요하다. 이를 위해서 shell 에서는 -e 옵션을 넣어주어 하나하나씩 명시하지만 yml 파일에서는 environment: 지시어 영역 내부에 모두 작성해준다.
그런데 app: 영역에서도 environment: 가 존재한다. 왜냐하면 워드프레스인 app 컨테이너는 MySQL 컨테이너인 db에 접속하여 데이터를 가져와야 한다. 따라서 db에 대한 환경변수를 명시해준다.
그런데 이 때, 잘 보면 app: 영역의 environment의 WORDPRESS_DB_HOST를 보면 db 라고 적혀있는 것을 볼 수 있다. 이는 위의 db 컨테이너를 가리키는 것이 맞다. 그런데 이것을 왜 작성했는지 이해하기 전에 왼쪽의 shell 에서 docker network 명령어에 대해 이해해야 한다. docker network는 일종의 컨테이너들 끼리의 네트워크를 형성하는 것인데, 위 예시로 들자면 app 컨테이너가 db 컨테이너랑 같은 네트워크에 지정을 하면, app 컨테이너에서 db라고 명시를 해주면 알아서 자신이 속한 네트워크 내부의 db 컨테이너로 찾아가는 것이다.
그런데 shell에서 이를 수행하기 위해서는 맨 처음에 docker network create [만들 네트워크 이름] 을 통해 만들어주어야 한다. 그리고 shell 명령어 끝에 보면 컨테이너를 run 할때 마지막 옵션에 --network [만든 네트워크 이름]을 명시해주는 것을 볼 수 있다. 이렇게 함으로써 app 컨테이너를 run 하는 명령어를 보면 -e "WORDPRESS_DB_HOST=db" 라고 환경을 설정해줌으로써 db 컨테이너에 접속이 가능한 것이다.
그런데 yml 파일을 사용하면 이런 네트워크를 형성해주는 작업이 필요가 없어진다. 즉, yml 파일 내부의 services 영역에 있는 모든 컨테이너들은 자동으로 하나의 네트워크를 형성해준다. 따라서 yml 파일의 db: 영역의 environment: 에 있는 WORDPRESS_DB_HOST:db:3306 이라는 지시어를 알아들을 수 있는 것이다.
따라서 위 라인별로 의미를 도식화하면 아래와 같아진다. 위 텍스트들로 잘 이해가 안간다면 해당 강의를 꼭 시청해보자. 참고로 호스트의 포트를 워드프레스 웹 서버 컨테이너와만 연결해놓은(.yml 파일에서 app: 영역에만 ports: 라는 부분이 있음!) 이유는 사용자가 웹서버에는 접근이 가능해야 사용자의 웹 브라우저에 표출이 되기 때문이다. 그리고 MySQL 컨테이너와 연결해놓지 않은 이유는 데이터에는 웹 브라우저 사용자가 접근을 하지 못하도록 막아야 되기 때문이다.
마지막으로 위와 같이 만든 docker-compose.yml 파일을 실행하는 방법에 대해 알아보자. 아래와 같은 명령어를 실행하면 알아서 docker-compose.yml 파일을 찾아 그 안에 들어있는 내용을 실행해준다.
docker-compose up
반면에, 실행한 docker-compose.yml 파일을 다시 끄려면 up을 down으로만 바꾸어주면 된다.
docker-compose down
끝으로, 인카토스라는 회사에서 감사하게도 제게 협찬을 해주신 제품을 하나 소개하려고 합니다. 그것은 바로 아래 사진의 Docker 컨테이너 각티슈 케이스입니다!
개발 공부를 하다 보면 원인불명의 에러 때문에 땀을 흘리거나 눈물(?)을 흘리기도 하는데요! 겨울철엔 감기라도 걸리면 모니터 앞에서 콧물을 흘리기도, 한여름엔 개발을 너무 열심히 한 나머지 땀을 흘리기도 합니다.
하지만 이 제품을 곁에 두고 개발을 하게 되면 귀여운 Docker 컨테이너가 제공하는 티슈 한 장을 편하게 뽑아 쓰면서 개발 텐션을 끊지 않고 이어갈 수 있답니다~! 특히, 마치 개발 관련 장비를 하나 늘린 것처럼 마음이 한켠 든든해지는 기분입니다! 해당 제품에 관심이 있으시다면 아래 링크로 들어가시면 됩니다. 다시 한 번 좋은 제품을 협찬해주신 인카토스에 감사인사 드립니다! :)
💡 판매처 인카토스 : https://incatos.shop/
'Container > 생활코딩 Docker' 카테고리의 다른 글
[Docker] 내가 만든 image를 Github Container 레지스트리에 업로드하기 (0) | 2021.09.24 |
---|---|
[Docker] 내가 만든 image를 Docker Hub에 Push시켜 공유하자 (0) | 2021.09.22 |
[Docker] build와 Dockerfile로 나만의 이미지를 만들어보자 (1) | 2021.09.21 |
[Docker] 내가 만든 Container를 image로 만들자!(commit, build, Dockerfile 활용하기) (0) | 2021.09.10 |
[Docker] Container의 파일시스템과 Host의 파일시스템 연결하기 (0) | 2021.08.23 |