Personal Study/Spring

[Spring] [AWS] Spring boot + Mysql + docker-compose AWS에 배포하기

vㅔ로 2022. 9. 23. 23:47
728x90

캡스톤으로 백엔드를 맡게 되었는데 아무것도 경험해보지 못한 것들 투성이라 정말 정말 정말 많은 오류들을 만났다...

팀플이다보니 포기할 수도 없고 그냥 죽기살기로 성공해야만 했는데 다행히 성공했다!

그 과정들을 기록 겸 블로그에 공유한다.

 

docker-compose는 물론이고, Spring도 처음, AWS 배포도 처음입니다. 

따라서 다음 글에는 오류가 있을 수 있으며 잘못된 부분은 지적해주시면 감사하겠습니다. 

 

Spring 프로젝트는 배포할 어떤 프로젝트도 좋다.

나는 캡스톤 프로젝트를 사용했다.

Dockerfile 만들기

FROM openjdk:11-jdk
EXPOSE 8080
CMD ["./mvnw", "clean", "package"]
ARG JAR_FILE=./build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

Spring boot 프로젝트는 .jar 파일로 배포했다.

프로젝트 빌드 과정을 적어둔 파일이다.

EXPOSE 부분에는 spring boot가 실행될 포트 번호를 적어주면 된다. 

 

(*부정확할 수 있음*) 원래는 application.properties 파일에 port 번호를 바꿔주었었는데, 제대로 작동하지 않았다.

Dockerfile에 EXPOSE를 넣어주니 정상적으로 작동했는데, 이것이 직접적인 이유가 된 지는 잘 모르겠다. 

 

docker-compose.yml 만들기

version : "3.3"
services:
  database:
    image: mysql:8.0.30
    restart: always
    container_name: database
    environment:
      MYSQL_DATABASE: bogeo
      MYSQL_ROOT_PASSWORD: 1234
    volumes:
      - ./db:/var/lib/mysql
    ports:
      - "3306:3306"
    networks:
      - springboot-mysql-net
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: always
    ports:
      - "8080:8080"
    depends_on:
      - database
    container_name: bogeo_app
    environment:
      SPRING_DATASOURCE_URL: jdbc:mysql://database:3306/bogeo?useSSL=false&allowPublicKeyRetrieval=true
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: 1234
    networks:
      - springboot-mysql-net
networks:
  springboot-mysql-net:
    driver: bridge

인터넷에 있는 자료들을 참고해서 만들었다.

<database>

- image : mysql 이미지의 버전을 써준다.

- restart : 연결이 안 될 때 바로 꺼지지 말고 다시 시작할 수 있도록 설정 해준다.

- container_name : 만들 컨테이너의 이름을 작성한다. (나의 경우, Mysql 도커 컨테이너의 이름은 "bogeo"가 된다.)

- environment

     - MYSQL_DATABASE: 컨테이너 안의 database들 중에서 어떤 것을 사용할 지 기록하는 부분이다. 나의 경우 bogeo 데이터 베이스를 이용할 예정이라 bogeo라고 적었다.

    - MYSQL_ROOT_PASSWORD: root의 비밀번호

- volumes: 내가 이해하기로는 mysql 컨테이너 관련 데이터 (/var/lib/mysql 의 데이터들)을 로컬의 디렉터리에 저장하라는 뜻인 것 같다. 즉, {로컬 디렉터리 주소}:/var/lib/mysql 로 작성하면 된다.

- ports: 외부포트:컨테이너내부포트 로 이해하면 된다. 도커의 3306 포트를 외부에 3306으로 노출하는 것 같다.

- networks: 컨테이너가 연결될 네트워크를 설정한다.

<app>

- build

    - context: Dockerfile의 위치

    - dockerfile: 도커파일의 이름(?)

- restart : 위 설정과 동일하다.

- ports : 마찬가지로 도커의 8080 포트를 외부에 8080으로 노출한다.

- depends_on: database 컨테이너가 올라가고 나서 app 컨테이너가 실행될 수 있게 하는 것 같다.

- container_name : 컨테이너 이름 설정

- environment

    - SPRING_DATASOURCE_URL :

       jdbc:mysql/{사용할 mysql 컨테이너 이름}:{포트번호}/{mysql 컨테이너 내부 데이터베이스 이름}?{이외 설정들} 으로 이해하면 된다.

      이 부분을 이해하기가 참 난해했는데, 여러 글을 찾다보니 이해하게 됐다. 

    - SPRING_DATASOURCE_USERNAME: database의 user 이름을 적어준다. 나는 root를 사용했다.

    - SPRING_DATASOURCE_PASSWORD: 위에 적어둔 user의 비밀번호를 적는다.

- networks: 컨테이너가 연결될 네트워크를 설정한다.

<networks>

두 컨테이너를 연결할 네트워크를 생성한다.

네트워크 이름은 springboot-mysql-net이라고 지었고, driver의 종류는 bridge로 설정했다.

application.properties

이 부분에서 굉장히 삽질을 많이 했다. 

특히 spring.datasource.url을 도대체 어떻게 작성해야 할 지 몰라 곤란했다. 

정말 여러 가지를 시도해봤던 것 같다. (내가 정말 아무것도 몰랐다는 증거..)

내가 사용한 데이터베이스는 MySQL이었기 때문에 참고하면 좋을 것 같다.

 

** 주의 **

내가 사용한 MySQL 버전은 8.0.30이었는데, 8.xx 버전은 spring.jpa.database-platform 속성이 org.hibernate.dialect.MySQL8Dialect 여야 한다. 

인터넷에 있는 코드를 그대로 가져오는 바람에 버전이 호환이 안 되어 고생을 많이 했다.

다른 분들은 참고하셔서 적기를 바란다. 

# mysql
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://0.0.0.0:3306/bogeo?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=1234

# jpa
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect

# debug
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate.sql=DEBUG
logging.level.jpa=DEBUG

# port change
server.port=8080

혹시 몰라 코드 전문을 올린다.

 

이상하게 다른 분들은 url에 docker-compose 데이터베이스 컨테이너 이름을 넣어도 잘만 되던데 나는 잘 안 됐다...

잘 살펴보니 docker database의 주소가 0.0.0.0:3306 이길래 지푸라기 잡는 심정으로 해봤는데 됐다. 

혹시 이 부분에서 곤란을 겪고 있으신 분들은 docker inspect의 Ports를 확인해보시면 좋을 것 같다.

 

나의 경우 다음과 같은 상황이었다. (해당 docker는 포트 번호가 다른데, 예를 들면 다음과 같이 나온다는 뜻입니다)

AWS EC2 배포

AWS EC2 인스턴스 생성 글은 유명한 글이 많으니 생략하도록 하겠다.

EC2 보안 그룹 설정 중에서도 삽질을 많이 했는데 그 부분은 다음 글로 작성할 것이다.

https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-EC2-%EA%B0%9C%EB%85%90-%EC%82%AC%EC%9A%A9-%EA%B5%AC%EC%B6%95-%EC%84%B8%ED%8C%85-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-EBS-AMI?category=947439 

 

[AWS] 📚 EC2 개념 원리 & 사용 세팅 💯 총정리 (Instance / EBS / AMI)

EC2 (Elastic Compute Cloud) 개념 EC2란 Amazon Elastic Compute Cloud의 줄임말로서 AWS에서 제공하는 클라우드 컴퓨팅이다. 독립된 컴퓨터를 임대해주는 서비스로서 AWS의 대표적인 서비스, 대표적인 상품이다..

inpa.tistory.com

위 포스팅을 참고하여 AWS EC2 서버 설정을 했다.

 

나는 Window 10을 사용하고 있어 puTTY를 사용해서 SSH 연결을 했다.

(puTTY 사용법도 여기에서는 다루지 않는다. 좋은 글들이 많으니 찾아보시면 좋을 것 같다)

로그인 한 후 프로젝트 폴더 최상단으로 들어간다.

이 위치에서 다음 명령어를 친다.

docker-compose up --build -d

-d 옵션을 주면 docker-compose를 백그라운드에서 실행한다.

이렇게 창이 뜨면 정상적으로 실행되는 것이다.

Dockerfile에 설정했던 EXPOSE 포트로 접속하면 서버가 배포 된다! (와!)

 

퍼블릭 IPv4 주소 혹은 퍼블릭 IPv4 DNS 주소 뒤에 포트를 붙이면 접속할 수 있다.

Ex. http://xx.xxx.xxx.xx:8080 

 

PostMan 으로도 잘 접속되는 것을 확인할 수 있다.

 

느낀점

언제나 삽질을 하며 느끼는 거지만, 이 삽질이 언제까지일까, 끝나기는 할까, 이게 의미는 있을까, 하며 생각하지만 돌아보면 항상 크게 도움이 됐던 것 같다.

이번에도 docker-compose를 쓰려고 했던 것이 아니다.

사실 AWS 배포 전에 docker-compose 설정을 해뒀는데 잘 안 되어서 방치해두고 있었다.

그런데 AWS 배포 때 docker-compose를 써보려고 하니, 예전에 삽질했던 그 기억이 나에게 큰 도움이 되었다.

그때는 이해 안 되었던 것들이 다시 하니 이해가 되는 것이었다. 

뭐든 하다가 포기 하지 말고, 계속 삽질해보자. 마지막에 삽에 걸리는 것은 성공이라는 글자일지도 모른다.

앞으로도 캡스톤 화이팅 해야지.

728x90

'Personal Study > Spring' 카테고리의 다른 글

[Spring] Thymeleaf TemplateInputException 해결  (0) 2022.08.25