728x90

내가 만든 프로젝트를 다른 사람이 실행하려 할 때 DB에 스키마와 테이블이 없어서 오류가 발생할 수 있다. JPA를 이용하여 @Entity와 같은 어노테이션을 이용하면 스키마만 지정해줬을 때 자동으로 테이블을 생성해 주지만 안타깝게 지금은 마이바티스만 적용했기 때문에 테이블을 만들어줘야한다. 그렇다고 DDL을 모두 올리면서 "이렇게 만드시고 실행하시면 됩니다~" 하면 나라도 귀찮아서 안할게 분명하기 때문에 자동으로 해결해보고자 한다.


자동화가 목적이기에 DB와 내가 만든 프로젝트를 동시에 띄우는데 편리한 도커 컴포즈를 적용해보기로 했다.

1. DB의 정보가 담긴 init.sql 파일 작성 (위치: 프로젝트 내에서 최상단 디렉토리 (개인 취향에 맞춰 수정 가능))

CREATE DATABASE IF NOT EXISTS playground;
USE playground;

-- playground.main definition
CREATE TABLE IF NOT EXISTS `main` (
                        `seq` bigint NOT NULL AUTO_INCREMENT,
                        `title` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
                        `content` varchar(1000) COLLATE utf8mb4_unicode_ci NOT NULL,
                        `created_at` datetime NOT NULL,
                        `updated_at` datetime DEFAULT NULL,
                        PRIMARY KEY (`seq`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- playground.board definition
CREATE TABLE `board` (
                         `seq` bigint NOT NULL AUTO_INCREMENT COMMENT '게시글 시퀀스',
                         `title` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '게시글 제목',
                         `content` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '게시글 내용',
                         `author` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '게시글 작성자',
                         `created_at` datetime NOT NULL COMMENT '생성일자',
                         `updated_at` datetime DEFAULT NULL COMMENT '수정일자',
                         PRIMARY KEY (`seq`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
  • 이 부분은 내 프로젝트 기준이기에 각자 프로젝트에 맞춰 수정해주면 된다.

2. Dockerfile 작성 (위치: 프로젝트 내에서 최상단 디렉토리 (개인 취향에 맞춰 수정 가능))

FROM openjdk:8
ARG JAR_FILE=build/libs/*.war
COPY ${JAR_FILE} app.war

ENV DOCKERIZE_VERSION v0.6.0
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && tar -C /usr/local/bin -xzvf dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
    && rm dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz

CMD dockerize -wait tcp://db-mysql:3306 -timeout 20s java -jar /app.war
  • docke-compose를 이용하여 여러 프로젝트를 띄울 때 스프링부트가 DB보다 먼저 실행될 경우 에러가 나면서 컨테이너가 꺼지기 때문에 이를 방지하기 위해 DOCKERIZE 를 사용
  • docker-compose에서 depends_on과 restart: always를 사용해도 결과는 같지만 DB가 완전히 켜지기 전까지 스프링부트가 계속 껐다 켜졌다를 반복하기 때문에 이번에는 사용 X
  • 효율적인 도커 이미지를 위해선 openjdk:8-jre 또는 alpine 같은 가벼운 베이스 이미지를 추천하지만 DOCKERIZE 를 사용하기 위해선 JDK를 사용해야 함

3. docker-compose.yml 작성 (위치: 프로젝트 내에서 최상단 디렉토리 (개인 취향에 맞춰 수정 가능, 도커 파일과 같은 경로에 두는 것을 추천))

version: '3'

services:
  database:
    container_name: db-mysql
    image: 'mysql:8'
    ports:
      - '13306:3306'
    volumes:
      - './init.sql:/docker-entrypoint-initdb.d/init.sql'
      - db:/var/lib/mysql
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_unicode_ci
      - --skip-character-set-client-handshake

    environment:
      MYSQL_ROOT_PASSWORD: 1234

  my-app:
    container_name: my-app
    ports:
      - '8080:8080'
    build:
      context: .
      dockerfile: Dockerfile

volumes:
  db: {}

4. application.yml 수정

# 수정 전
spring:
  datasource:
    jdbc-url: jdbc:log4jdbc:mysql://localhost:13306/playground
    
# 수정 후
spring:
  datasource:
    jdbc-url: jdbc:log4jdbc:mysql://db-mysql:3306/playground
    
# 도커 컴포즈로 여러 컨테이너를 띄울 때는 해당 컴포즈로 생성된 네트워크로 묶이기에 내부 컨테이너 정보를 사용하는 것이 좋다
# db의 host 변경: localhost > docker-compose에서 작성한 DB 컨테이너명
# db의 port 변경: 13306 > 3306

5. 빌드 방식 변경(build.gradle)

plugins {
	// 스프링 부트는 jar 빌드를 기본제공하기에 war로 빌드할 수 있게 변경
	id 'war'
}
  • 이 부분은 JSP파일을 사용한다던가 외장 WAS를 사용하는 등의 특별한 이유가 없으면 굳이 하지않아도 되는 과정이다.
  • 만약 war로 할 필요가 없는 프로젝트라면 Dockerfile 의 내용을 변경해야한다. (war > jar)
  • 더 자세한 설명은 링크1, 링크2

위와 같이 파일을 생성, 수정하면 준비는 끝났다.

남은건 커맨드 2개만 입력하면 된다. 아래의 두 커맨드를 순서대로 입력하면 DB의 스키마부터 테이블의 생성 및 컬럼 생성, 스프링부트 프로젝트 실행까지 한번에 할 수 있게된다.

# 스프링부트 프로젝트 빌드
./gradlew bootjar

or

./gradlew bootwar
# 도커 컴포즈 실행
(docker-compose.yml 이 있는 디렉토리로 이동하여)
docker-compose up -d

or

(해당 디렉토리에 docker-compose.yml이 없는 경우)
docker-compose -f {도커 컴포즈파일이 있는 경로}/docker-compose.yml -d

 

+ Recent posts