Java

Spring boot + Minio + Docker 예제를 만들어보자(1)

Yukart 2022. 11. 21. 22:15
반응형
본 게시물은 2개로 나누어져 있습니다. (1) 에서는 전반적인 환경을 설정하는 파일을 설명합니다. 
Minio를 이용한 File 저장을 익히는 목적이 있으며, Minio의 동작원리와 사용법을 익히는데 중점을 두었기 때문에 서비스 운영에 목적을 두고 계시다면 수정이 필요할 수 있습니다.

우선, 제가 생각한 전체적인 아키텍처를 그림으로 보자면 이렇습니다.

처음 설계한 minio 이벤트 별 순서도

가장 서버에게 부하를 주는것은 빈번한 다운로드, 클라이언트 입장에서도 가장 많이 이용하는 서비스가 다운로드 일 것입니다. 그래서 다운로드의 순서가 조금 특이한데 세부 설명을 좀 드리자면

1. 다운로드를 하고싶은 file을 요청합니다.(파일 경로를 특정할 수 있는 request)
2. 서버는 request에 있는 특정 경로를 추정하고 minio에게 파일 접근권한이 미리 서명된 preSignedURL을 요청합니다.
3. minio는 서버의 accessKey 를 비롯한 인증정보를 통해 믿을 수 있는 서버임을 확인하고 preSignedURL을 발급해줍니다.
4. 서버는 요청에 대한 응답(presinged)을 합니다.
5. 받은 url로 client가 minio server와 직접 통신합니다.

 실제 파일 업로드는 클라이언트에서 진행되기 때문에 트래픽 및 대역폭을 신경쓰지 않아도 됩니다.
 반면 upload & delete & update 같은 경우는 서비스에 따라 파일을 검증하고 따로 가공할 일이 많기 때문에 통제권 자체를 서버에 남겨두었습니다. 물론 필요하다면 이것들 또한 client에게 위임할 수 있습니다. 
 마지막으로 Minio Notification 기능인데 web hook 방식으로 파일에 대한 작업이 끝났다면 Minio가 서버의 엔드포인트에 json 형태로 응답을 줍니다. 이것을 활용하여 트랜잭션 처리를 다양하게 활용할 수 있습니다.

 다만 학습을 더 하면서 알게된 사실이 있습니다.
 파일이 읽기 전용/공용 이고 파일을 읽기 전용/공용으로 유지하려는 경우 미리 서명된 URL을 사용하는 복잡성을 추가할 필요가 없습니다.

 

자바를 빌드하기 위해 가장 기초적인 build.gradle

minio를 보다 효과적으로 사용하기 위해 minio 라이브러리 종속성 추가가 핵심

 

plugins {
    id 'org.springframework.boot' version '2.7.2'
    id 'io.spring.dependency-management' version '1.0.12.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    implementation 'io.minio:minio:8.4.2'
    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.googlecode.json-simple:json-simple:1.1.1'

    implementation 'com.fasterxml.jackson.core:jackson-core:2.13.3'
    implementation 'com.fasterxml.jackson.module:jackson-module-kotlin'
    implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.1'
}

tasks.named('test') {
    useJUnitPlatform()
}

 

implementation 'io.minio:minio:8.4.2' 가 핵심입니다.

 

 

다음은 Docker 컨테이너로 기동시키기 위한

dockercompose.yaml

version: "3.9"

services:
  java-minio-template:
    image: yourid/java-minio-template
    build:
      context: .
      dockerfile: Dockerfile
    restart: always
    ports:
      - "8080:8080"
    environment:
      - VERSION=0.0.1
    volumes:
      - .:/application
    working_dir: /application
    command: |
      sh -c "
        chmod +x ./gradlew;
        ./gradlew --stop;
        ./gradlew build --continuous --quiet &
          ./gradlew bootRun;
      "
  minio:
    image: minio/minio:RELEASE.2022-05-08T23-50-31Z
    command: server /data --console-address ":9001"
    environment:
      - MINIO_ENDPOINT=minio:9000
      - MINIO_ROOT_USER=yuihmoo
      - MINIO_ROOT_PASSWORD=yuihmoopwd
      - MINIO_NOTIFY_WEBHOOK_ENABLE_TEMPLATE=on
      - MINIO_NOTIFY_WEBHOOK_ENDPOINT_TEMPLATE=http://host.docker.internal:8080/bucket/notify
    restart: always
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - data_minio:/data

volumes:
  db_data:
  data_minio:
MINIO_NOTIFY_WEBHOOK_ENABLE_TEMPLATE=on - MINIO_NOTIFY_WEBHOOK_ENDPOINT_TEMPLATE=http://host.docker.internal:8080/bucket/notify

MINIO_NOTIFY_WEBHOOK_ENABLE 는 Minio 웹훅 서비스 기능을 활성화 하겠다는 것이고 그 후에 _(언더스코어) 뒤에 문자는 웹훅으로 활용되는 queue에 이름을 지정할 수 있습니다.
아무것도 지정해주지 않으면 default 값으로 queue 이름이 적용 됩니다.

MINIO_NOTIFY_WEBHOOK_ENDPOINT 는 작업이 다 끝났을 때 알려주기 위한 엔드포인트 url 입니다.

 

 

Docker 이미지 빌드를 위한

DockerFile

FROM openjdk:8-jdk-alpine as builder
WORKDIR /application
COPY . .
RUN chmod +x ./gradlew \
  && ./gradlew build -x test

FROM openjdk:8-jdk-alpine
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ="Asia/Seoul"
RUN apk add tzdata
WORKDIR /application
ENV VERSION=0.0.1
COPY --from=builder /application/build/libs .
CMD ["sh", "-c", "java -jar /application/java-minio-template-${VERSION}-SNAPSHOT.jar"]

 

 

스프링 부트 환경변수

application.properties

#Minio
minio.url=http://host.docker.internal:9000
minio.access.key=yuihmoo
minio.access.secret=yuihmoopwd

#Tomcat
server.port=8080

#Spring
spring.servlet.multipart.maxFileSize=100MB
spring.servlet.multipart.maxRequestSize=100MB
server.tomcat.max-http-form-post-size=100MB
server.port 는 굳이 정해주시지 않아도 boot 기본 8080입니다.
혹시 제대로 서비스를 운영하고 싶으시다면
당연하게도 minio access key 혹은 secret 같은 경우 민감한 정보이기 때문에 외부에서 주입받는것이 더 좋습니다.
# 주의 : spring.servlet.multipart.maxFileSize=100MB 는 레퍼런스로 따를 만한 사이즈가 아닙니다.
값을 임의로 넣은 것이므로 만들려는 서비스에 따라 다르게 설정하고 사용하시면 됩니다.

이상으로 1편을 마치겠습니다. 2편에는 java 코드 구현체를 다뤄볼 예정입니다. 아래는 제가 공부하면서 참조한 레퍼런스들 첨부하겠습니다.

 

https://min.io/docs/minio/container/index.html

 

MinIO High Performance Object Storage — MinIO Object Storage for Container

Run the following command to install the latest stable MinIO Client package using Homebrew. brew install minio/stable/mc Run the following commands to install the latest stable MinIO Client package using a binary package for Apple chips. curl -O https://dl

min.io

https://play.minio.io:9443/

Java Client API Reference

 

Java Client API Reference — MinIO Object Storage for Linux

Map - Contains form-data to upload an object using POST method.

min.io

 

반응형