ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 5/8 TIL | 쉼표 작업 일지 #34. 배포의 축복(?)은 끝이 없네😵
    📝 기록/작업 기록 2023. 5. 9. 00:38

    서버 배포부터 시작. fly.io를 통해서 프론트/백을 모두 배포하려고 한다. 먼저 서버를 띄우기 전에 데이터베이스를 PostgreSQL로 설정을 하고, production(=배포)은 H2 메모리가 아닌 PostgreSQL을 바라보게 application.properties 파일을 설정했다.

    설정 완료!

    Dockerfile을 통해 배포를 진행하기 때문에 Dockerfile 생성하여 아래와 같이 입력하였다.

    // 1. open jdk 중에 sdk 버전을 셋업
    FROM eclipse-temurin:17
    
    // 2. 아래 경로에 프로그램을 위치시킴
    WORKDIR /u/myapp
    
    // 3. [plain]이 붙은 파일을 제외하고 나머지 jar 파일을 해당 경로에 이동시킴
    COPY build/libs/*[^plain].jar ./
    
    // 4. 서버 포트는 8000, 프로필은 production을 바라보게 하고 jar 파일 실행시킴
    CMD java -Dserver.port=8000 -Dspring.profiles.active=production -jar *.jar

    jar 파일을 컨테이너를 띄워 실행함으로써 해당 프로젝트가 혹시라도 코드를 수정하게 되면, ./gradlew clean bootJar 명령어를 실행해 가장 최신의 jar 파일을 추출해야 한다.

    그 후, fly launch 명령어와 fly deploy 명령어를 통해 프로젝트를 배포한다. 이제 터미널과 Fly에서 제공하는 Monitoring 로그를 통해 배포가 잘 진행되는지 지켜보면 된다.

    하.지.만....

    deploy failed.... why..?🥹

    Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'javax.persistence.jdbc.url', 'hibernate.connection.url', or 'hibernate.dialect') 에러가 뜨며 배포가 실패했다.

    해당 jar 파일이 로컬과 컨테이너 환경에서도 잘 돌아갔기 때문에 별 문제가 없어야 하는데.. 왜일까...!? 배포하게 되면 기존에 로컬에서 사용하던 DB url이 아닌 배포된 PostgreSQL 주소를 바라봐야 하기 때문인가 했는데, 이는 application.properties에 production 용 DB url을 이미 연결해 놓은 상황.. build.gradle에 PostgreSQL Driver 또한 dependencies로 추가되어 있는 상황...

    헤매던 도중 application.properties에 production용 환경을 별도로 더 설정해 줘서 아래와 같이 해결했다. 사실 이전에 마카오 기프트샵 서버를 배포할 때는 아래와 같은 설정을 별도로 해주지 않아도 됐었는데 왜 이번엔 이런 오류가 발생했는지 의문스럽긴 하다.

    #---
    spring.config.activate.on-profile=production
    spring.datasource.url=jdbc:${DATABASE_URL}
    spring.datasource.driver-class-name=org.postgresql.Driver
    spring.jpa.database=postgresql
    spring.jpa.hibernate.ddl-auto=update

    하지만 배포의 축복은 거기서 끝이 아니었으니.... 해결을 했다고 판단한 이유가 이제 더 이상 그 에러가 뜨지 않기 때문이었다.. ^^;; 두 번째 문제는 아래와 같다.

    Caused by: javax.net.ssl.SSLHandshakeException: Remote host terminated the handshake Caused by: java.io.EOFException: SSL peer shut down incorrectly 와 같은 에러가 뜨며 또 배포 실패..

    postgresql 리모트 호스트가 terminated되었다는 의미는.. SSL 연결 핸드쉐이크 중에 원격 호스트가 연결을 종료하여 SSLHandshakeException 오류가 발생했다는 것을 의미하는 같은데... 그 말인 즉.. 지금 DB 용량이 부족해서 계속 원격 호스트랑 연결이안 된다는 것 아닌가 싶었다..! 그래서 256MB였던 메모리를 512MB로 scale up하고 재배포를 시도해 봤으나 역시나 실패...

    우선 이틀간 이렇게 거의 한 50번의 deploy를 시도해 봤고, 계속 fail하는 이 시점에서.. 이 방법을 해결할 방법은 Fly.io 커뮤니티에 현 상황을 정리한 글을 작성해서 올려볼까 생각도 했으나 아무리 봐도 이건 Fly의 문제가 아니라 Spring Boot 내부의 문제인 거 같아 고민하던 도중, 때마침 이 글을 발견하게 되었다.

    나와 비슷한 케이스 발견!

    기존에 나는 DATABASE_URL을 fly에서 제공하는 secrets 환경변수에 저장하고 사용하고 있었는데, 이때 아래와 같이 설정했었다.

    fly secrets set DATABASE_URL=
    "postgresql://{호스트네임}/postgres?user=postgres&password={패스워드}"

    그런데 지금 발생하는 문제는 Fly에서 내부적으로 작업을 처리하고 있는 SSL 통신이 충돌하기 때문에 생기는 에러이므로 쿼리스트링으로 sslmode를 disable하게끔 별도로 설정을 해줘야 했던 것이다.

    fly secrets set DATABASE_URL=
    "postgresql://{호스트네임}/postgres?user=postgres&password={패스워드}&sslmode=disable"

    그리하여 하여 위 코드와 같이 sslmode를 disable한다는 쿼리스트링까지 넣어 secrets를 설정했더니 드디어 제대로 배포가 이루어졌다!

    드디어 Health check passing!
    dead 아니고 running하는 나의 서버..

    근 이틀을 꼬박 서버 배포에 매달렸는데, 항상 배포는 매번 어려운 거 같다. 문제가 생겨도 이게 어떤 요소로 인해 생기는 오류인지 원인을 바로 파악할 수 있는 인사이트가 아직 모자라서 더 오래 걸리고 어려운 거 같지만.. 그래도 이렇게 계속 시도하면서 새로운 케이스가 등장할 때마다 열심히 기록해 두고, 해결해 나가면서 익숙해질 때까지 노력해야지!