1. 서론
이번 포스팅에선 docker-compose.yml 파일의 작성법을 정리했다.
본 포스트에선 3.9 버전의 docker-compose.yml을 기준으로 작성되었으니 참고 바란다.
docker-compose란
다수의 컨테이너로 구성된 서비스를 구축 및 실행 관리할 수 있는 기능이고, 이러한 기능을 docker-compose.yml이라는 파일로 정의할 수 있다. docker-compose를 이용하면 기존 docker 명령어로 컨테이너를 생성하고, 네트워크를 생성 및 연결하는 등의 일련의 과정을 간편하게 자동화시킬 수 있다.
docker-compose를 사용하기 위해선 컨테이너로 만들 이미지가 준비되어있어야 한다. docker-hub에 올라가있는 이미지를 사용할 수도 있고, 따로 이미지를 만들어야 할 경우엔 Dockerfile을 작성하여 이미지를 빌드할 수도 있다.
이미지 빌드방법은 아래 포스트를 참고하길 바란다.
(포스트 추가 예정)
docker-compose.yml 파일은 일반적으로 프로젝트 루트에 위치해두고 프로젝트 루트위치에서 "docker-compose up" 명령어를 실행했을 때 자동으로 해당 docker-compose.yml을 찾아 컨테이너를 세팅해준다.
이제 docker-compose.yml 작성법에 대해 정리해보도록 하겠다.
2. docker-compose.yml 작성법
2-1. version
"version"은 docker-compose의 버전을 나타내는 구문이다. 일반적으로 docker-compose.yml의 맨 첫줄에 작성한다.
여기에 작성하는 버전에 따라 호환되는 Docker Engine의 버전이 달라지는데, 아래 첨부된 문서를 참고해서 사용해야하는 환경의 Docker Engine의 버전에 맞추어 가장 최신 버전으로 작성하도록 한다. (아무리 못해도 swarm 기능을 쓸 수 있는 version 3 이상의 버전을 사용하도록 하자)
작성법은 아래와 같다.
version: '{Version기입}'
예시)
version: '3.9'
2-2. services & container
"services"는 다수의 컨테이너를 하나의 서비스로 묶어줄 때 사용한다. services 하위에 컨테이너들을 정의하면 해당 컨테이너들은 하나의 서비스로 묶이게 된다.
작성 방법은 아래와 같다. 아래는 node-app과 mysql을 하나의 서비스로 묶은 예시이다. 컨테이너를 정의할 때 "app", "mysql"처럼 이름을 정의해주면 해당 이름으로 컨테이너명이 설정된다. 컨테이너의 상세 설정 방법은 4번에 정리해놓았다.
version: "3.9"
services:
app:
image: node:latest
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:app
env_file: app.env
mysql:
image: mysql:5.7
volumes:
- ./mysql-data:/var/lib/mysql
env_file: mysql.env
2-3. container 상세 설정 방법
컨테이너를 생성하기 위해선 실행할 이미지, 바인딩할 포트, 바인딩할 볼륨, 환경변수, 등을 설정해주어야 한다. 이를 설정하는 구문은 아래와 같다.
"image": 컨테이너로 실행할 로컬 도커 이미지 리스트에 있는 이미지나 Docker Hub에 있는 이미지 설정한다. 기본적으로 "{이미지명}:{태그}" 형식으로 기재한다. 태그 부분은 생략이 가능하며, 생략 시 가장 최신 버전의 이미지를 pull하게 된다.
"build": "image"를 이용해 이미 빌드된 이미지를 가져오는 것이 아닌, Dockerfile이 있는 경로를 지정해 docker-compose 실행 시 이미지를 즉석으로 빌드하여 사용하게 된다..
"dockerfile": 빌드할 Dockerfile의 이름이 "Dockerfile"이 아닌 경우 파일명을 지정할 수 있다.
"ports": 호스트와 컨테이너의 포트 바인딩을 설정한다. Dockerfile의 "EXPOSE"와 동일한 기능이다.
"volumes": 호스트의 지정된 경로로 컨테이너의 볼륨을 마운트하도록 설정할 수 있다.
"container_name": 컨테이너의 이름을 지정할 수 있다.
"command": 컨테이너 실행 완료 후 컨테이너의 쉘에서 실행시킬 쉘명령어를 설정할 수 있다.
"environment": 환경변수를 설정할 수 있다. 단, docker-compose.yml 안에서 정의된 환경변수는 컨테이너 쉘 내부에서 정의된 환경변수들 보다 낮은 우선순위를 가진다.
"env_file": "environment"와 동일하게 환경변수를 설정할 수 있다. 하지만 차이점은 env 파일을 이용해 환경변수를 설정할 수 있어서 docker-compose.yml에 앱시크릿을 넣지 않고 env파일로 관리할 수 있어서 소스 컨트롤에 앱시크릿이 올라가게 되는 불상사를 방지할 수 있다.
"depends_on": 컨테이너 간의 종속 관계를 설정 할 수 있다. 예를 들어 DB 컨테이너와 App 컨테이너가 있을때 App 컨테이너가 DB 컨테이너와 연결되어 정보를 가져온다고 하면, App 컨테이너는 DB 컨테이너에 종속성을 가지게 되므로 컨테이너가 실행이 될때 App 컨테이너보다 DB컨테이너가 우선 실행되어야 할 필요가 있다. 이런 상황을 위해 "depends_on"을 이용하면, 컨테이너 간의 종속성을 정의하고 실행 순서를 설정할 수 있다.
"restart": 컨테이너의 재시작과 관련된 설정을 정의할 수 있다. "no"로 설정할 경우 무조건 수동으로 재시작해주어야 한다. "always"로 설정할 경우 컨테이너를 수동으로 종료시키지 않는 이상 항상 재시작되게 된다. "on-failure"로 설정할 경우 컨테이너에 오류가 발생했을 때만 재시작하게 된다.
2-4. network
docker에는 보안적인 문제를 위해 독립적인 네트워크를 구성하여 컨테이너 간 통신을 할 수 있도록 기능을 제공하고 있다.
docker-compose를 이용하면 그러한 네트워크를 간편하게 구성할 수 있다.
기본적으로 docker-compose를 실행하게 되면 "{현재디렉토리명}_default" 라는 이름의 default network가 생성되고 docker-compose.yml을 통해 생성된 모든 컨테이너는 별도의 네트워크 설정이 없다면 전부 default network에 연결되게 된다. 하지만 필요에 따라 별도의 네트워크가 필요할 경우 커스텀 네트워크를 구성해줄 수도 있다. 방법은 아래와 같다.
version: "3.9"
services:
app:
image: node:latest
command: sh -c "yarn install && yarn run dev"
ports:
- 3000:3000
working_dir: /app
volumes:
- ./:app
env_file: app.env
networks:
- default
- new_net
mysql:
image: mysql:5.7
volumes:
- ./mysql-data:/var/lib/mysql
env_file: mysql.env
networks:
new_net:
driver: bridge
위처럼 "networks"라는 구문으로 새로운 네트워크를 정의하고, 해당 네트워크에 연결할 컨테이너에 정의한 네트워크를 컨테이너 상세 설정 아래의 "networks"에 추가해주면 된다. 이때, default network에 연결을 하고싶다면 "default"라는 네트워크를 추가해주어야 한다.
*참고: network driver 종류
"bridge": 컨테이너를 설치하면 default로 연결되는 네트워크로, 동일한 호스트 컴퓨터에 컨테이너들 간 통신을 위한 옵션이다.
"host": 호스트 컴퓨터와 동일한 네트워크 환경을 사용하는 옵션이다. 컨테이너의 호스트 이름도 호스트 컴퓨터의 이름과 동일하다.
"overlay": docker swarm 서비스와 독립실행 컨테이너간 또는 서로다른 docker 데몬에 있는 여러 개의 독실실행형 컨테이너간의 통신이 필요할 때 사용되는 옵션이다.
"ipvlan": 호스트 인터페이스를 가상화하는 옵션으로, MAC 주소와 IP 주소를 부여하여 실제 네트워크에 컨테이너를 직접 연결시키는 방식이다.
"macvlan": 하나의 네크워크 인터페이스를 여러개의 별도 MAC 주소를 가지는 네트워크 인터페이스로 분리하여 사용할 수 있는 옵션이다.
"none": 아무 네트워크를 쓰지 않고 내부에 lo 인터페이스만 존재하는 옵션이다. 이 옵션은 컨테이너의 IP를 구성하지 않으며 다른 컨테이너뿐만 아니라 외부 네트워크에도 액세스할 수 없다.
'SW > DevOps' 카테고리의 다른 글
[DevOps] Github Actions로 브랜치별 Firebase 배포 설정하기 (0) | 2023.01.21 |
---|---|
[DevOps] NGINX Proxy Manager와 CloudFlare를 이용해 로컬 네트워크 내에서 일관된 웹 개발 테스트 환경 구성하기 (0) | 2022.10.31 |
[DevOps] Netlify에 CloudFlare DNS 연동하기 (0) | 2022.10.09 |
[DevOps] Scale-Up과 Scale-Out (0) | 2022.06.23 |
[DevOps] Docker + Jenkins를 통해 Docker 배포 자동화 구축하기 (1) | 2022.06.08 |