[Docker] Spring boot + MariaDB | docker-compose๋กœ ์‹คํ–‰ํ•˜๊ธฐ

๊ธฐ์กด์— ๊ฐœ๋ฐœํ•˜๋˜ ํ”„๋กœ์ ํŠธ์— docker-compose๋ฅผ ์ ์šฉ์‹œ์ผœ๋ณด์•˜๋‹ค. ์ถ”๊ฐ€๋กœ Nginx๋ฅผ ๋„์›Œ 3๊ฐœ์˜ spring server์— ๋กœ๋“œ๋ฐธ๋Ÿฐ์‹ฑ๋„ ํ•ด๋ณด์•˜๋‹ค. 

 

๊ทธ ์ „์— docker compose ์‹คํ–‰ ์ข…๋ฃŒ ๋ช…๋ น์–ด์— ๋Œ€ํ•ด ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค.

๋„์ปค๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์บ์‹ฑ์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— docker compose๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ์ˆ˜์ • ์‚ฌํ•ญ์ด ์ ์šฉ๋˜์ง€์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ข…์ข… ์žˆ์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜์™€ ๊ฐ™์€ ๋ช…๋ น์–ด๋กœ ์‹คํ–‰, ์ข…๋ฃŒ๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค.

  • ์‹คํ–‰: docker compose up --force-recreate
  • ์ข…๋ฃŒ: docker compose down --rmi all

 

Spring boot + MariaDb

application.yml

spring:
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://database:3306/colony
    username: root
    password: 1234
  servlet:
    multipart:
      max-file-size: 30MB
      max-request-size: 30MB
  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        default_batch_fetch_size: 1000
        dialect: org.hibernate.dialect.MySQL8Dialect
  mvc:
    async:
      request-timeout: -1

 

docker-compose.yml

version: "3.8"                                          # ํŒŒ์ผ ๊ทœ๊ฒฉ ๋ฒ„์ „
services:                                               # ์ด ํ•ญ๋ชฉ ๋ฐ‘์— ์‹คํ–‰ํ•˜๋ ค๋Š” ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ์ •์˜
  database:
    container_name: database
    build:
      dockerfile: Dockerfile
      context: ./database
    image: dgjisnu/database
    environment:
      - MARIADB_DATABASE=colony
      - MARIADB_ROOT_PASSWORD=1234
    volumes:
      - ./database/config:/etc/mysql/conf.d
      - ./database/data:/var/lib/mysql
    ports:
      - "13306:3306"      # ์ ‘๊ทผ ํฌํŠธ ์„ค์ • (์ปจํ…Œ์ด๋„ˆ ์™ธ๋ถ€:์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€)

  colony-app:
    container_name: colony-app
    build: .
    depends_on: # DB, REDIS ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹คํ–‰๋œ ๋‹ค์Œ WEB์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.
      - database
    image: dgjinsu/colony-app
    environment:
      - MAIL_PASSWORD=${MAIL_PASSWORD}
      - MAIL_USERNAME=${MAIL_USERNAME}
      - S3_ACCESS_KEY=${S3_ACCESS_KEY}
      - S3_SECRET_KEY=${S3_SECRET_KEY}
    ports:
      - "80:8080"
    restart: always # depends on์€ ์‹คํ–‰ ์ˆœ์„œ๋งŒ ์ปจํŠธ๋กค ํ• ๋ฟ,

์—ฌ๊ธฐ์„œ ์‚ฝ์งˆ์„ ๊ฝค๋‚˜ ํ–ˆ๋‹ค.

์ดˆ๋ฐ˜์— DB๋งŒ ๋„์ปค๋กœ ๋„์›Œ๋‘๊ณ  ์„œ๋ฒ„๋Š” ๋กœ์ปฌ๋กœ ์‹คํ–‰ํ•˜๋Š” ํ˜•ํƒœ๋กœ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ–ˆ๋‹ค. ์ด๋•Œ DB ports ๋ถ€๋ถ„์— "3306:3306" ์œผ๋กœ ํ•˜๊ฒŒ ๋˜๋ฉด local์— ๊น”๋ฆฐ mysql ๋•Œ๋ฌธ์— ํฌํŠธ ์ถฉ๋Œ์ด ๋‚œ๋‹ค. ๋”ฐ๋ผ์„œ ์™ธ๋ถ€ ํฌํŠธ๋ฅผ 13306์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ์—ˆ๊ณ  application.yml ํŒŒ์ผ ์•ˆ์— DB์—ฐ๊ฒฐ ๋กœ์ง์— url: jdbc:mariadb://localhost:13306/ ์œผ๋กœ ์ˆ˜์ •ํ•ด์ฃผ์—ˆ๋‹ค. 

๊ฐœ๋ฐœ์ด ๋๋‚˜๊ณ  ์Šคํ”„๋ง๋„ ์ปจํ…Œ์ด๋„ˆ๋กœ ๋„์šฐ๊ธฐ ์œ„ํ•ด ์ˆ˜์ •ํ•˜์˜€๊ณ  db์—ฐ๊ฒฐ ๋ถ€๋ถ„ ์ฝ”๋“œ๋ฅผ url: jdbc:mariadb://database:13306/ ์œผ๋กœ ๋ฐ”๊ฟ”์ฃผ์—ˆ๋‹ค. ํ•˜์ง€๋งŒ docker compose up ์„ ํ–ˆ์„ ๋•Œ ์ž๊พธ db์—ฐ๊ฒฐ์— ์‹คํŒจํ–ˆ๋‹ค. 

์›์ธ์€ ํฌํŠธ์˜€๋‹ค. ๊ธฐ์กด์—๋Š” ๋„์ปค ์™ธ๋ถ€์—์„œ ๋„์ปค ๋‚ด๋ถ€ ์ปจํ…Œ์ด๋„ˆ๋กœ ์ ‘๊ทผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— 13306 ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ๋งž์•˜์ง€๋งŒ ์ปจํ…Œ์ด๋„ˆ๋กœ ๋„์›Œ์ง„ ์Šคํ”„๋ง์—์„  db ์ปจํ…Œ์ด๋„ˆ๋กœ ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„  3306 ํฌํŠธ๋กœ ์ ‘๊ทผํ•ด์•ผํ–ˆ๋‹ค. 

์กฐ๊ธˆ๋งŒ ์ƒ๊ฐํ•˜๋ฉด ํ•ด๊ฒฐ๋  ๋ฌธ์ œ์˜€์ง€๋งŒ ๋„์ปค์— ๋Œ€ํ•œ ๊ฐœ๋…์ด ๋ถ€์กฑํ–ˆ์—ˆ๋‹ค.  

 

environment ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” docker-compose.yml ํŒŒ์ผ๊ณผ ๋™์ผ ๊ฒฝ๋กœ์— .env ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค. 

์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ง€์› ๋‹ค ๋‹ค์‹œ ๋„์›Œ๋„ DB ๋ฐ์ดํ„ฐ๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„  ๋ณผ๋ฅจ ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค. ./database/data:/var/lib/mysql ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋งˆ์šดํŠธ ์‹œ์ผœ์ฃผ์—ˆ๋‹ค. 

 

Spring Dockerfile

FROM openjdk:17-jdk
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

 

database Dockerfile

FROM mariadb:10

ENV TZ=Asia/Seoul

database conf

[client]
default-character-set=utf8mb4

[mysql]
default-character-set=utf8mb4

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
skip-character-set-client-handshake

[mysqldump]
default-character-set=utf8mb4

 

 

 

Nginx + 3 * Spring boot + mariaDB

์œ„ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ Nginx์—์„œ 80ํฌํŠธ๋กœ ๋“ค์–ด์˜ค๋Š” ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ 3๊ฐœ๋กœ ๋ถ„์‚ฐ์‹œ์ผœ์ค€๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

 

application.yml์€ ์œ„ ์™€ ๊ฐ™๋‹ค.

 

docker-compose.yml

version: "3.8"                                          # ํŒŒ์ผ ๊ทœ๊ฒฉ ๋ฒ„์ „
services:                                               # ์ด ํ•ญ๋ชฉ ๋ฐ‘์— ์‹คํ–‰ํ•˜๋ ค๋Š” ์ปจํ…Œ์ด๋„ˆ๋“ค์„ ์ •์˜
  database:
    container_name: database
    build:
      dockerfile: Dockerfile
      context: ./database
    image: dgjisnu/database
    environment:
      - MARIADB_DATABASE=colony
      - MARIADB_ROOT_PASSWORD=1234
    volumes:
      - ./database/config:/etc/mysql/conf.d
      - ./database/data:/var/lib/mysql
    ports:
      - "13306:3306"      # ์ ‘๊ทผ ํฌํŠธ ์„ค์ • (์ปจํ…Œ์ด๋„ˆ ์™ธ๋ถ€:์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ถ€)

  colony-app1:
    container_name: colony-app1
    build: .
    depends_on: # DB, REDIS ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹คํ–‰๋œ ๋‹ค์Œ WEB์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.
      - database
    image: dgjinsu/colony-app1
    environment:
      - MAIL_PASSWORD=${MAIL_PASSWORD}
      - MAIL_USERNAME=${MAIL_USERNAME}
      - S3_ACCESS_KEY=${S3_ACCESS_KEY}
      - S3_SECRET_KEY=${S3_SECRET_KEY}
    restart: always # depends on์€ ์‹คํ–‰ ์ˆœ์„œ๋งŒ ์ปจํŠธ๋กค ํ• ๋ฟ,
    ports:
      - '8080:8080'
  colony-app2:
    container_name: colony-app2
    build: .
    depends_on: # DB, REDIS ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹คํ–‰๋œ ๋‹ค์Œ WEB์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.
      - database
    image: dgjinsu/colony-app2
    environment:
      - MAIL_PASSWORD=${MAIL_PASSWORD}
      - MAIL_USERNAME=${MAIL_USERNAME}
      - S3_ACCESS_KEY=${S3_ACCESS_KEY}
      - S3_SECRET_KEY=${S3_SECRET_KEY}
    restart: always # depends on์€ ์‹คํ–‰ ์ˆœ์„œ๋งŒ ์ปจํŠธ๋กค ํ• ๋ฟ,
    ports:
      - '8081:8080'
  colony-app3:
    container_name: colony-app3
    build: .
    depends_on: # DB, REDIS ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์‹คํ–‰๋œ ๋‹ค์Œ WEB์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.
      - database
    image: dgjinsu/colony-app3
    environment:
      - MAIL_PASSWORD=${MAIL_PASSWORD}
      - MAIL_USERNAME=${MAIL_USERNAME}
      - S3_ACCESS_KEY=${S3_ACCESS_KEY}
      - S3_SECRET_KEY=${S3_SECRET_KEY}
    restart: always # depends on์€ ์‹คํ–‰ ์ˆœ์„œ๋งŒ ์ปจํŠธ๋กค ํ• ๋ฟ,
    ports:
      - '8082:8080'


  proxy-be:
    image: nginx:1.21.5-alpine
    container_name: colony-nginx
    restart: always
    depends_on:
      - colony-app1
      - colony-app2
      - colony-app3
    ports:
      - "80:80"
    volumes:
      - ./proxy/nginx-be.conf:/etc/nginx/nginx.conf

 

nginx-be.conf

events { worker_connections 1024; }
http{
    upstream colony-app {
    server colony-app1:8080;
    server colony-app2:8080;
    server colony-app3:8080;
    }
    server {
            listen 80;
    location / {
            proxy_pass http://colony-app;
            }
    }
}

์œ„์—์„œ ์‚ฝ์งˆํ•œ ๋•๋ถ„์— ์—ฌ๊ธฐ์„  ๋ฐ”๋กœ ์„ฑ๊ณตํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. app1, 2, 3์€ 8080, 8081, 8082 ํฌํŠธ๋ฅผ 8080ํฌํŠธ๋กœ ํฌ์›Œ๋”ฉ ์‹œ์ผœ์ฃผ์ง€๋งŒ nginx์—์„œ ์ ‘๊ทผํ•  ๋• ์ „๋ถ€ 8080ํฌํŠธ๋กœ ์ ‘๊ทผํ•ด์•ผ ํ•œ๋‹ค.