본문으로 건너뛰기

Mogenius를 활용한 도커 컨테이너 배포

· 약 14분
Jake Son

이전 포스트에서 적은 fly.io 와 비슷한 서비스를 제공하는 Mogenius 를 활용한 도커 컨테이너 배포에 대한 내용을 다룬다.

Fly.io 단점​

Fly.io 는 무료로 사용할 수 있는 서비스이지만, 무료 플랜에서 256MB 의 메모리만 지원하는 단점이 있다. 그래서 Spring Boot + JPA 를 사용하는 프로젝트를 배포할 때 OOM 에러가 발생하여 다른 서비스를 찾아보게 되었다.

Mogenius​

Mogenius 도 도커 컨테이너 배포를 지원하는 서비스로 쿠버네티스 기반으로 동작한다. 저장소에 있는 Dockerfile 을 읽어서 이미지를 생성하고 배포한다. GitHub 과 연동하여 특정 브랜치에 커밋이 푸시되면 자동으로 배포가 동작한다. CD 설정을 직접 해야하는 fly.io 와 달리 자동으로 설정해주기 때문에 편리하다.

글 작성 시점으로 무료 플랜에서는 다음 햘당량을 받을 수 있다.

  • 0.5 CPU Core
  • 1GB RAM
  • 5GB traffic
  • 2GB storage
정보

추후에 달라질 수 있는 내용이라 공식 사이트에서 직접 확인하는 것을 권장한다.

메모리를 1GB 지원하기에 MySQL 컨테이너를 띄우기 용이하다. fly.io 에서는 결제정보를 입력해야 추가 사용량을 받을 수 있지만 Mogenius 회원가입만 해도 위의 사용량을 받을 수 있다. 특히 fly.io 에서 잘못 사용하다가 무료 사용량이 초과해 원치않는 비용이 청구될 수 있지만 Mogenius 에는 그런 걱정이 없다.

다만 Mogenius 는 fly.io 와 달리 작성일 기준으로 독일 리전만 지원한다. 하지만 개발용도로 사용할 목적이라면 큰 문제는 아니다.

MySQL 컨테이너​

이번 포스트에서는 Spring Boot 웹서버와 MySQL 컨테이너를 배포하는 방법을 다룬다.

회원가입​

먼저 Sign Up 에 접속하여 회원가입을 한다. 아직 소셜 로그인 기능은 없어서 직접 이메일 주소를 입력해야 한다. Sign Up 버튼을 누르면 입력한 이메일로 인증 메일이 오는데, 인증을 완료하면 로그인이 가능하다.

regester

Cloudspace 생성​

로그인을 완료하면 Cloudspace 를 생성을 위한 페이지에 접속하게 된다. Create Cloudspace 버튼을 눌러서 다음으로 진행한다.

cloudspace

원하는 cloudspace 이름을 입력하고, Free Plan 이 선택된 것을 확인하고 Create now 버튼을 누른다.

space-name

Service 생성​

이후 cloudspace 대시보드 페이지에 접속하게 되는데 리로스 할당량, 사용중인 서비스 등을 확인할 수 있다. 중간에 Stages 항목을 볼 수 있는데 이는 개발/운영 같은 배포환경을 의미한다라고 생각하면 된다. 무료 플랜에서는 Production Stage 만 사용할 수 있기에 크게 신경 쓸 내용은 없다. 현재는 Production Stage 에 아무런 서비스가 없으며 Add 를 누른다.

서비스는 하나의 컨테이너라고 생각하면 되며 현재 3가지 방법으로 생성할 수 있다.

  • Bring your own code: GitHub 저장소를 활용해 배포
  • Use a template: Mogenius 에서 제공하는 템플릿을 활용해 샘플 컨테이너 배포
  • Container Imgae: DockerHub 같은 컨테이너 저장소의 이미지를 활용해 배포

첫 번째 방법은 저장소에 있는 Dockerfile 을 활용하며 두 번째는 Mogenius 에서 제공하는 샘플용 저장소를 활용한다. Dockerfile 을 활용해 커스텀한 설정이 필요한 경우가 아니라면 세 번째 방법을 사용할 수 있다. 공식 mysql 이미지를 그대로 사용할 것이기에 Container Image 를 선택한다.

add-stage

컨테이너 이미지 설정​

이제 컨테이너 설정을 하게되는데 사실 docker 에 익숙한 사람이라면 문서없이도 설정할 수 있을 정도로 간단하다. Service Name 에 원하는 서비스 이름을 넣어주고 Container Image 에는 사용할 이미지를 입력한다. mysql 공식 이미지를 사용할 것이기에 mysql 을 입력한다. 원하는 경우 태그까지 넣어서 특정 버전으로 고정할 수도 있다.

image-name

Resource limits​

Settings 의 Resource limits 에 컨테이너에 할당할 자원량을 배정할 수 있다. Mogenius 는 유효한 이메일 계정만 있으면 제한없이 계정을 만들 수 있으므로 여러 컨테이너를 각각 다른 계정을 활용해 띄울 수 있다. 그래서 모든 할당량을 다 배정해도 무방하다.

resource

Environment Variables​

Environment Variables 에는 컨테이너 내부에서 사용할 환경변수와 volume mount 설정을 할 수 있다. Add Variable 을 눌러 각 항목을 추가하며 Type 을 선택해 환경변수나 volume mount 를 추가할 수 있다.

Plaintext 을 선택해 평문으로 환경변수를 넣어줄 수 있으며 Volumn Mount 를 선택해 mysql data 를 저장할 디렉토리를 지정할 수 있다. 다음과 같은 설정을 추가한다.

좌측 메뉴의 File Browser 를 통해 손쉽게 볼륨 데이터를 확인할 수 있다.

  • Plaintext
NameValue설명
MYSQL_RANDOM_ROOT_PASSWORDtrue랜덤하게 root 비밀번호를 생성한다.
MYSQL_DATABASE원하는 값생성할 데이터베이스 이름을 지정한다.
MYSQL_USER원하는 값생성할 사용자 이름을 지정한다.
MYSQL_PASSWORD원하는 값생성할 사용자 비밀번호를 지정한다.
  • Volumn Mount
NameSourceDestination
mysql-datamysql-data/var/lib/mysql

env

Ports​

Port 설정은 컨테이너 내부포트를 외부로 노출하기 위한 용도로 쓰인다. 사실 하나의 cloudspace 에서 웹과 디비 서비스를 추가해 사용한다면 컨테이너 끼리만 통신하게 설정할 수 있다. 보안을 강화하려면 디비는 외부로 노출하지 않는것이 좋지만 웹을 다른 cloudspace 에서 띄우는 경우라 설정하였다. Type 은 TCP 를 선택하고 외부 포트는 3306 을 입력하고 Expose 에 체크된 것을 확인한다.

port

외부 접속 url 확인​

Create Service 버튼을 눌러 컨테이너를 생성하면 외부에서 접속할 수 있는 주소와 포트가 설정되며 이를통해 접속할 수 있다. 서비스 상세 페이지에서 Hostname 을 누르고 External hostname 항목에 보이는 url 을 기억해둔다.

external-url

Spring Boot 컨테이너 생성 및 MySQL 연동​

이제 Spring Boot 컨테이너를 생성하고 MySQL 컨테이너와 연동해보자.

이번 글에서 예제로 사용할 저장소는 santa-close-server 이다.

저장소 설정​

우선 도커 이미지를 빌드하기 위한 Dockerfile 을 저장소 루트에 생성한다. 예제 프로젝트는 gradle 과 멀티모듈을 사용하며 server-app 모듈을 빌드하고 생성한 jar 파일을 실행하도록 설정하였다.

주의

Mogenius 는 보안을 위해 컨테이너를 root 계정으로 실행하는 것을 허용하지 않는다. 따라서 Dockerfile 에서 root 가 아닌 게정으로 프로그램을 실행하도록 설정해야 한다.

# 빌드 stage
FROM gradle:jdk17 AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
# 빌드 수행
RUN gradle build --no-daemon -x test

# 실행 stage
FROM ghcr.io/graalvm/jdk:ol8-java17-22.2.0
ENV LC_ALL=C.UTF-8
# app 유저 생성
RUN useradd app
USER app
# jar 파일 복사
COPY --from=build /home/gradle/src/server-app/build/libs/server-app.jar app.jar
# jar 파일 실행
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/urandom", "-jar", "app.jar"]

디비접속 정보와 같은 항목은 환경변수를 통해 설정할 수 있게 다음과 같은 파일이 존재한다.

server-app/src/main/resources/application-live.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ${DATABASE_URL}
username: ${DATABASE_USERNAME}
password: ${DATABASE_PASSWORD}
# 그 외 다른 환경변수들..

서비스 등록​

이번에는 Bring your own code 를 선택해 웹서버를 추가해보자. Service name 에 원하는 값을 넣어주고 Repository 에서 GitHub 계정을 연결해 저장소를 선택할할 수 있도록 만든다.

정보

GitHub 계정 연동없이 public 저장소 url 을 활용할 수 있지만 CI/CD 가 설정되지 않는다.

연결이 완료되었으면 Git Repository 항목에서 배포를 원하는 저장소를 선택하고 Git Branch 에서 자동빌드를 원하는 브랜치를 선택한다. Dockerfile 이 프로젝트 루트가 아닌 다른곳에 있거나 빌드를 실행할 디렉토를 다르게 가져가려면 Dockerfile Name, Docker Context 를 수정한다.

web-name

Environment Variables 에서는 앞서 application-live.yml 에서 필요로하는 환경변수를 등록하면 된다. 추가로 SPRING_PROFILES_ACTIVE 의 값을 live 로 설정해 spring 프로필을 live 로 설정한다.

value 에 일부 특수문자가 들어가는 경우 환경변수 등록이 안되는 경우가 있는데 그럴 때에는 Key Vault 를 활용한다. 쿠버네티스의 secret 과 비슷한 기능으로 민감한 정보를 암호화해 저장한 후 컨테이너 내부에서는 복호화한 값을 사용하게 된다.

key-vault

값을 추가한 후 환경변수 메뉴에서 해당 key 를 사용하도록 설정해야한다.

add-key-vault

Ports 항목에서 내부 포트는 8080 Type 은 HTTPS 로 설정하도록 한다. 이러면 외부에서 https 접속할 수 있는 url 을 얻을 수 있고 http -> https 리디렉트 설정까지 자동으로 이루어진다.

web-port

Create Service 버튼을 누르면 모든 설정이 완료된다. 이후 생성된 url 을 통해 서버가 정상적으로 동작하는지 확인해본다.

마무리​

지금까지 Mogenious 를 사용한 컨테이너 배포를 살펴보았다. 아직 서비스가 생긴지 얼마 지나지 않아 서비스가 지속적으로 유지될지 여부는 불투명하지만 그 전까지는 유용하게 사용할 수 있을거같다. 아직 문서가 부족한 편이지만 설정 자체가 간단한 편이라 큰 어려움 없이 진행할 수 있을거라 생각한다. 추가로 비슷한 기능을 제공하는 Render 라는 서비스도 있는데 추후에 살펴보도록 하겠다.