본문 바로가기
한화시스템 Beyond SW Camp/데브옵스

[Docker] Docker Compose

by taeh00n 2025. 3. 10.

Docker Compose : 여러 개의 컨테이너를 한 번에 정의하고 관리할 수 있는 도구

 

보통 애플리케이션은 데이터베이스, 백엔드, 프론트엔드 등 여러 컨테이너로 구성되는데, 이를 하나의 docker-compose.yml 파일에서 관리할 수 있도록 도와준다

= 하나의 명령어로 여러 개의 컨테이너를 실행하고, 네트워크 및 볼륨을 자동으로 설정

 

docker-compose.yml

서비스(컨테이너), 볼륨, 네트워크 등을 정의하는 구성 파일

docker-compose.yml 문법

services:
  컨테이너 이름:
    image: 실행할 이미지
    environment:
      - 변수이름:값
    volumes:
      - 본체경로:컨테이너경로
    ports:
      - 본체포트:컨테이너포트
    command:["명령어", "옵션", "옵션"]

docker-compose.yml 코드 예시

services:
  nginx:
    image: nginx:latest
    volumes:
      - ./frontend/default.conf:/etc/nginx/conf.d/default.conf
      - ./frontend/dist:/usr/share/nginx/html
    ports:
      - "80:80"

  backend:
    image: openjdk:17-ea-slim-buster
    depends_on:
      - database
    environment:
      - DB_URL=database:3306/web
      - DB_ID=root
      - DB_PASSWORD=qwer1234
    ports:
      - "8080:8080"
    volumes:
      - ./backend/cth_test_backend-0.0.1-SNAPSHOT.jar:/app.jar
    command: ["java", "-jar", "/app.jar"]

  database:
    image: mariadb:latest
    volumes:
      - ./db:/var/lib/mysql
    environment:
      - MARIADB_ROOT_PASSWORD=qwer1234
      - MARIADB_DATABASE=web
    ports:
      - "3306:3306"

depends_on을 해주면 backend가 database를 의존하기 때문에 database가 먼저 실행된 후 backend가 실행이 된다.

=> 실행하자마자 backend가 비정상적으로 종료되는 일이 사라진다.

파일 구조
실행결과

 

3개의 컨테이너(nginx, backend, database) 가 생성

Nginx 컨테이너

프론트엔드(정적 파일) 제공 및 백엔드 프록시 역할

백엔드 컨테이너 (backend)

Java 백엔드 애플리케이션 실행

데이터베이스 컨테이너 (database)

MariaDB 데이터베이스 실행

 

=> 이 docker-compose.yml 파일을 실행하면 완전한 풀스택 애플리케이션이 컨테이너 환경에서 실행


HAProxy (haproxy.cfg)

listen stats
    bind *:9000
    mode  http
    option dontlog-normal
    stats enable
    stats realm Haproxy\ Statistics
    stats uri /stats

frontend webserver
  bind *:80
  mode http
  default_backend nginx-server
  
backend nginx-server
  mode http
  balance roundrobin 
  option httpchk GET /test.html
  server nginx1 web1:80 check
  server nginx2 web2:80 check

Nginx(default.conf)

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

     location /api/ {
        proxy_pass http://backend:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

docker run 명령어 설명

docker run 
  --name backend    # 컨테이너 이름을 'backend'로 지정
  -p 8080:8080       # 호스트의 8080 포트를 컨테이너의 8080 포트와 연결 (포트포워딩)
  -v "C:\~~~~":/app.jar  # 호스트의 특정 파일("C:\~~~~")을 컨테이너 내부 "/app.jar"에 마운트 (볼륨 설정)
  -e DB_USER=root     # 환경 변수 DB_USER 설정 (root 사용자)
  -e DB_URL=jdbc:mariadb://~/web   # 데이터베이스 연결 주소 환경 변수 설정
  -d                 # 컨테이너를 백그라운드(-d)로 실행
  openjdk:17-ea-slim-buster   # 사용할 Docker 이미지 (OpenJDK 17의 slim 버전)
  java -jar /app.jar  # 컨테이너 내에서 실행할 명령어 (자바 애플리케이션 실행)