학습목표

Spring Boot + MySQL 을 결합해서 실행시키는 것이 목표임.

(이때는 SpringBoot에 Mysql의 URL, ID, PW, PORT 정보가 필요하다.)

 

도커의 특성 리마인드 & 내부 네트워크의 장점

도커의 특성으로 JDK와 MySQL이 로컬에 설치되어있지 않아도 해당 Image를 다운로드 받아서 실행시켜버리면 되니까 매우 편리하다.

또한 도커 내부 네트워크를 만들어서 SpringBoot와 MySQL을 묶어놓으면 두 개의 독립적인 컨테이너는 서로 통신이 가능하게 된다.

외부 Volume을 만들어서 MySQL에 연결하여 MySQL Container와 독립적으로 작동하도록 해놓는 것도 잊지말자.

 

 

학습 준비

실습 디렉토리 : ex08

스프링 부트 GIT : git clone https://github.com/codingspecialist/docker-test-server.git

※ 우분투에서 처음 git clone을 했다면 로그인하라고 뜨는데 github id는 그대로 쓰고, pw는 personal token을 발급받아서 복사해주면 된다.

(settings > (사이드 메뉴의 맨마지막) Developer Settings > Personal access toekns)

 

1. docker-test-server  (Spring Boot)

 

[SpringBoot Server Dockerfile 작성] ( ~ex08/docker-test-server 디렉토리에 작성)

FROM openjdk:11-jdk-slim

WORKDIR /app

# COPY만 docker-compose 파일의 위치를 기반으로 작동함
# docker-test-server내부에 있는 모든 파일을 WORKDIR인 /app으로 COPY를 한다는 의미이다.
COPY . .

# RUN은 현재 파일의 위치를 기반으로 작동함
RUN chmod +x ./gradlew
RUN ./gradlew clean build

# build.gradle에 어떤 설정을 하면 .jar파일이 1개가 만들어진다. (원래는 2개만들어짐)
# 만들어진 jar파일의 이름을 app.jar 로 변경한다는 의미이다. (실행하기 편하게)
#ARG JAR_FILE=build/libs/*.jar
#COPY ${JAR_FILE} app.jar

# 로컬에 빌드된게 아니라 컨테이너 내부에서 빌드된거니까 위에있는 COPY를 쓰면 안되고 RUN으로 실행시켜
야한다.
ENV JAR_PATH=/app/build/libs
RUN mv ${JAR_PATH}/*.jar /app/app.jar

ENTRYPOINT ["java", "-jar","-Dspring.profiles.active=prod","app.jar"]

주석처리된 내용 중에 #build.gradle에 어떤 설정을하면 .jar파일이 1개만 만들어진다는 내용이 있는데

git clone받은 파일 중 build.gradle 내용 맨 마지막 내용을 보면

jar {
        enabled = false
}

이러한 내용이 있다. 해당 내용이 "프로젝트명-버전-plain.jar" 파일을 생성하지 않고 즉시 실행가능한 executable.jar파일("프로젝트명-버전.jar")만 생성 하게 하는 옵션이다. 해당 옵션을 사용하지 않으면 plain.jar, executable.jar 두개의 파일이 생성된다.

관련링크 : https://dev-j.tistory.com/22

 

Plain jar vs Executable jar(feat. plain jar 생성 방지)

스프링 부트 gradle 플러그인 2.5 버전부터 gradle 빌드 시 JAR 파일이 2개 생성된다. 별도의 설정을 하지 않았을 때 하나는 "프로젝트 이름-버전.jar", 다른 하나는 "프로젝트 이름-버전-plain.jar"이라는

dev-j.tistory.com

 

2. docker-test-db (MySQL)

아래의 내용들은 ~ex08/docker-tset-db 디렉토리에 작성 해야한다.

 

[init.sql 작성] 

init.sql은 Docker Container가 실행될 때 자동으로 해당 SQL을 실행시켜 DB 초기화를 진행시키기 위한 파일이다. (컨테이너를 내렸다가 다시 올려도 실행되는지는 확인해봐야함!)

CREATE TABLE user_tb(
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(50)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO user_tb (name) VALUES ('John');
INSERT INTO user_tb (name) VALUES ('Jane');

 

[MySQL Dockerfile 작성] 

FROM mysql:8.0

#docker-entrypoint-initdb.d로 복사 해준 sql은 자동으로 실행된다. (문서에 나와있다고함)
COPY init.sql /docker-entrypoint-initdb.d

ENV MYSQL_ROOT_PASSWORD=root1234
ENV MYSQL_DATABASE=metadb
ENV MYSQL_HOST=%

CMD ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]

 

 

3. docker-compose.yml 작성

docker-compose.yml파일은 ~ex08/docker-compose.yml 에 작성해주면 된다.

version: '3'

services:
  db:
    build:
      #context = Dockerfile의 위치-이걸 안잡아주면 COPY할 때 init.sql위치를 ex08(docker-compose.yml이 있는 곳)으로 봐버리는 문제가 생긴다.
      context: ./docker-test-db 
      dockerfile: Dockerfile
    ports:
      - 3306:3306
    volumes:
      - ./docker-test-db/store:/var/lib/mysql
    networks:
      - network

  server:
    build:
      context: ./docker-test-server
      dockerfile: Dockerfile
    restart: always
    ports:
      - 8080:8080
    depends_on:
      - db #db가 먼저 구축되고 나서 다 되면 server를 실행시키는 것을 의미한다.
    environment: #해당 값들은 application-prod.yml에서 ${SPRING_DATASOURCE_URL} 에서 사용한다.
      SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/metadb?useSSL=false&serverTimezone=UTC&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true
      SPRING_DATASOURCE_DRIVER: com.mysql.cj.jdbc.Driver
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: root1234
    networks: #동일 네트워크로 잡아주어야 datasource url에서 jdbc:mysql://db 로 쓸수있는 것이다. ip 로 안쓰고..
      - network

networks:
  network:

db쪽에서 init.sql 을 실행시킬 때 강사님은 Dockerfile에서 "/docker-entrypoint-initdb.d" 경로로 COPY를 하였지만 다른 분은 docker-compose.yml에서

volumes:

  - "./init/:/docker-entrypoint-initdb.d/" 

이런식으로 하신분들도 있다.

 

4. 컨테이너 실행

docker compose up -d --build

docker compose up -d --build 를 해주면 다시 이미지까지 빌드된다. 

 

+ Recent posts