1. 개념
- docker compose는 docker에서 사용하고자 하는 이미지를 바탕으로 컨테이너를 실행할 때, 컨테이너 실행 맥락에서 필요한 명령어를 작성한 yml 파일이다.
- docker compose를 이용하면, 복수의 컨테이너를 편리하게 생성 및 실행할 수 있다.
2. Docker compose의 이득
- docker compose의 가장 큰 이득은 복수의 컨테이너를 생성하고, 컨테이너 간 네트워크 연결을 docker-compose 한 파일 안에서 일괄적으로 처리할 수 있다는 것이다.
- 예컨대, 다음과 같은 상황에서 docker compose는 컨테이너를 실행하는 데 큰 이점을 가진다.
예시상황: 웹 어플리케이션을 실행하는 이미지와 DB 이미지를 각각 컨테이너로 실행시키고, 두 컨테이너를 연결한다.
1. docker-compose를 이용하지 않는 경우
- 웹 어플리케이션 이미지와 DB 이미지를 각각 생성한다. (이 떄, docker file을 이용할수도, docker hub에서 이미지를 pull 받아올 수 있겠다.)
- 각각의 이미지를 docker run 명령어로 컨테이너로 실행시킨다. 이미지가 2개이므로, 총 2번 실행하겠다.
=> 컨테이너로 실행시키기 전에, 두 컨테이너 간 통신을 위한 네트워크를 구축한다.
=> 컨테이너를 실행시킬 떄, 생성한 네트워크를 두 컨테이너가 각각 사용할 것임을 명시한다.
2. docker-compose를 이용할 경우
- docker-compose 파일 안에서 컨테이너로 생성할 이미지들을 각각 명시해준다.
- docker-compose up 명령어로 docker-compose를 실행하여, 각각의 컨테이너를 실행한다.
- 요컨대, 도커에서 컨테이너는 직관적으로 비유하자면, 하나의 프로그램의 실행환경을 패키징한 이미지를 실행하는 가상의 머신 하나라고 할 수 있다. 위 예시에 빗대어 더 직관적으로 비유하자면, 웹 어플리케이션만을 실행하는 EC2 한 대, DB만 실행하는 EC2 한 대가 곧 컨테이너인 것이다.
- 그래서 복수의 컨테이너를 생성하고, 각 컨테이너 간 통신이 필요하다면, 네트워크 조성이 필요하다.
- docker의 기본적인 명령어들을 사용해서 이를 구축할 수 있으나, 이는 매우 번거로운 작업이다.
- docker-compose는 자체적으로 컨테이너 간 통신을 위한 네트워크를 조성해준다.
- 아울러, 복수의 컨테이너 생성을 위해, docker run을 여러번 실행할 필요 없이, docker-compose를 단 한번만 실행하면 된다.
- 이처럼, docker-compose는 특히 복수의 컨테이너를 생성하고 컨트롤할 때 정말 이로운 기술이라고 할 수 있겠다. 말 그대로, container를 compose하는 기술이다.
아래는 docker-compose 파일의 작성법과 실행 명령어에 대한 내용이다.
3. docker-compose 작성 및 실행방법
- 이 글에서는 docker-compose로 컨테이너를 실행하는데 필요한 기본적인 내용만 기술하겠다.(간단한 실습을 해본 경험에 기반한 내용이다.)
1) docker compose 작성
- docker compose는 다음과 같이 작성될 수 있다.
services:
app:
build:
context: .
dockerfile: DockerFile
env_file:
- .env
ports:
- '3000:${PORT}'
command: node dist/main.js
- services: docker compose에서 생성할 컨테이너들의 list를 의미한다. 이하에 작성된 내용들이 컨테이너로 생성된다.
- app: services 내에서 생성하는 컨테이너에 붙이는 별칭이다. apps와 동일 수준의 line에 작성된 것은 모두 하나의 컨테이너임을 지칭한다. app 이하에 작성되는 내용이 컨테이너를 생성할 때 사용할 이미지에 대한 규격을 의미한다.
- build: 필자는 build 명령어는 image를 dockerfile로 생성할 경우에 사용하는 명령어로 이해했다.
- context: dockerfile이 위치한 경로
- dockerfile: 컨테이너를 생성할 때, 사용할 이미지에 대한 명세가 담긴 dockerfile
- env_file: 컨테이너에서 사용할 env 파일의 경로
- ports: host 포트와 연결할 컨테이너의 포트
- command: 컨테이너 생성 후 실행할 명령어
- 복수의 컨테이너를 사용할 경우, 다음처럼 할 수도 있다.
services:
db:
image: <사용할 db의 image 태그명>
...(이하 컨테이너 실행 시 필요한 맥락 및 명령어)
app:
depeends_on:
- db
위 예시와 동일
- 소개하고 싶은 것은 image 파라미터다.
- docker-compose에서 image 파라미터는 단순히 이미 로컬의 도커에서 생성되어 있는 image만을 값으로 넣을 수 있는 것이 아니다.
- 놀랍게도, docker-hub에 공개되어 있는 image들의 태그명을 입력하면, 해당 image를 가져와서 컨테이너를 생성한다고 한다.
- 이 때, app과 db 컨테이너 간의 연결은 위에 서술한 바처럼 docker-compose를 실행하면, 자체적으로 컨테이너 간의 네트워크가 생성된다.
- 그러므로, app 이미지 내 소스코드에는 이미 db 연결을 위한 코드와 계정(?) 정보들이 포함되어 있을 것이므로, app에서 사용하는 환경변수만 app 컨테이너에 주입시키면 app과 db 컨테이너 간 네트워크 연결이 성사될 수 있다.
- app의 depends_on 파라미터는 컨테이너가 의존하는 다른 컨테이너를 지칭하는 것이다. 즉, app 실행 전에 db가 먼저 실행되어야 하는 선행관계를 설정하는 것이다.
다음은 docker compose 실행을 위한 터미널 명령어이다.
2) docker compose 터미널 명령어
- docker compose 실행을 위해서는 다음과 같이 명령어를 작성할 수 있다.
# docker compose를 실행하여 컨테이너 생성/실행
docker-compose up -build -d
# docker compose 실행 종료
docker-compose down
- docker-compose up 명령어에 사용된 두 파라미터의 의미는 다음과 같다.
=> build: docker-compose up으로 컨테이너 생성 시, 이미지를 다시 새로이 빌드하는 것을 의미한다.
=> d: 백그라운드 환경에서 컨테이너를 실행하는 것을 의미한다.
- docker-compose up 명령어 실행 시, 로컬 도커에 해당 이미지가 없다면, 이미지가 생성되고 그 이미지를 바탕으로 한 컨테이너가 실행된다.
- 이외에도 다양한 파라미터들을 활용할 수 있지만, 기본적인 내용만 기술하였다.
- docker와 docker-compose에는 많은 parameter들을 작성할 수 있고, 명령어도 다양하다. 이에, 보다 자세한 내용은 공식 사이트를 참고하는 것이 좋을 것이다.
4. 참고자료
https://www.youtube.com/watch?v=EK6iYRCIjYs&t=748s
https://docs.docker.com/reference/