시스템 구축과 관련된 명령어를 하나의 텍스트 파일(정의 파일)에 기재해 명령어 한 번에 전체를 실행하고 종료와 폐기까지 한 번에 하도록 도와주는 도구
예를 들어 하나의 서버가 돌아가기 위해서는 프론트엔드, 백엔드, DB 서버 이 세 가지가 작동해야 하는데, 이걸 일일이 명령어를 이용해서 실행하면 무척이나 번거롭다. 게다가 DB가 master-slave 등으로 구성되어야 할 경우 그 복잡도는 더 커진다.
도커 컴포즈는 이러한 번거로움을 yaml파일을 통해 한 번에 할 수 있도록 한다.
version: "3"
services:
[컨테이너 이름]:
image: [이미지 이름]:[버전]
ports:
- [Host Port]:[Container Port]
volumes:
- .[Host path]:[Container path]
environment:
- [Key]=[Value]
command: ["명령어", "띄어쓰기는", "쉼표와", "따옴표"]
depends_on:
- [먼저 실행될 컨테이너]
이미지 이름을 제외하면 나머지 속성은 전부 선택사항(꼭 전부 넣을 필요는 없다.)
version: "3"
services:
frontend:
image: nginx:latest
ports:
- 80:80
volumes:
- ./frotend/dist:/usr/share/nginx/html
- ./frotend/nginx/default.conf:/etc/nginx/conf.d/default.conf
environment:
- ABC=qwer
backend:
image: openjdk:17-ea-slim-buster
ports:
- 8081:8080
volumes:
- ./backend/build/libs/[빌드 파일].jar:/app.jar"
command: ["java", "-jar", "/app.jar"]
db:
image: mariadb:latest
ports:
- 3306:3306
volumes:
- ./db:/var/lib/mysql
environment:
- MARIADB_ROOT_PASSWORD=qwer1234
- MARIADB_DATABASE=test
⚡여기서 volumes의 경로는 절대경로보다는 상대경로를 적는 걸 추천⚡

실행 버튼을 하나씩 눌러도 되지만 services를 누르면 세 개가 동시에 실행된다.

하나의 service 안에서 3개의 컨테이너가 동시에 돌아가는 걸 확인할 수 있다.
여기서 잠깐 짚고 넘어가자면, docker desktop에서 mariaDB를 실행할 때 MARIADB_ROOT_PASSWORD를 지정해야만 정상적으로 작동이 되었다. 그러므로 docker-compose에서는 environment에 넣으면 되는데, MARIADB_DATABASE를 설정하면 database도 자동으로 생성되는 걸 확인할 수 있다.
이는 MariaDB 이미지 설명 페이지에서도 확인할 수 있는데,
if [ "$MARIADB_USER" -a "$MARIADB_PASSWORD" ]; then
CREATE USER '$MARIADB_USER'@'%' IDENTIFIED BY '$MARIADB_PASSWORD';
GRANT ALL PRIVILEGES ON `$MARIADB_DATABASE`.* TO '$MARIADB_USER'@'%';
➡️ 처음 실행될 때 database와 user가 환경변수로 설정되어있으면 유저에게 해당 데이터베이스에 접근하는 권한까지 알아서 준다.
✅ 동작 순서 (컨테이너 첫 기동 시)
1. docker-compose up → db 서비스 시작
2. /var/lib/mysql 폴더가 비어 있을 경우에만
3. 다음 환경 변수를 읽고 초기 설정 실행
❗ 중요한 조건! (초기화는 한 번만 동작)
• /var/lib/mysql 디렉토리가 비어 있을 때만 초기화 동작이 실행된다.
• 이미 데이터가 존재하는 경우(./db 볼륨이 남아 있는 경우),
다시 초기화 스크립트가 실행되지 않는다.
-> 그러므로 이미 만들어진 컨테이너에 환경변수를 추가했다면 설정 또한 따로 해주어야 한다.
만약 DB 초기 데이터 삽입이나 SQL 스크립트 자동 실행이 필요하다면 docker-entrypoint-initdb.d 폴더에 넣으면 된다.
HAProxy에 관한 사용법은 여기(클릭)에 정리되어 있다.
이전의 실습 내용을 보면 haproxy를 사용하기 위해서는 haproxy.cfg파일을 수정해야 한다는 걸 알 수 있다.
그러므로 적당한 위치에 haproxy.cfg 파일을 생성하고 기존의 코드와 위에서 확인한 설정을 참고하여 아래의 코드를 작성한다.
listen stats
bind *:9000
stats enable
stats uri /stats
stats realm Haproxy\ Statistics
frontend webserver
bind *:80
mode http
default_backend nginx-server
backend nginx-server
mode http
balance roundrobin
option httpchk GET /
server nginx1 localhost:81 check
server nginx2 localhost:82 check
여기서 주의할 점이, 마지막에 엔터가 들어가야 haproxy docker가 제대로 작동한다.
version: "3"
services:
haproxy:
image: haproxy:latest
container_name: haproxy
ports:
- "80:80" # 외부에서 접근할 포트
- "9000:9000" # HAProxy stats 페이지
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
depends_on:
- nginx1
- nginx2
nginx1:
image: nginx:latest
container_name: frontend1
ports:
- "81:80" # 내부에서 81 포트로 노출 -> HAProxy가 여기를 체크
volumes:
- ./frontend/dist:/usr/share/nginx/html
- ./frontend/nginx/default.conf:/etc/nginx/conf.d/default.conf
nginx2:
image: nginx:latest
container_name: frontend2
ports:
- "82:80" # 내부에서 82 포트로 노출 -> HAProxy가 여기를 체크
volumes:
- ./frontend/dist:/usr/share/nginx/html
- ./frontend/nginx/default.conf:/etc/nginx/conf.d/default.conf

시간이 지난 후 컨테이너를 끄고 캡쳐해서 동작 버튼은 불이 꺼졌지만 아무튼 컨테이너가 정상적으로 생성되어 작동되었다.