외국 유학생들이 우리 대학 적응을 돕도록 만드는 앱 개발을 진행하고 있다.
해당 앱에 대해 궁금하면 외국민 Github를 참조 바란다.
우리 앱 기능 중에서, 외국인들이 한국에서 자주 쓰이는 표현, 발표 스크립트 발음을 평가해주는 기능이 존재한다. 그래서 이걸 어떻게 구현할까 찾던중, Microsoft에서 발음평가 API를 발견하였다. 그래서 Spring 서버에서 이 기능을 사용하여 구현하였다.
https://learn.microsoft.com/ko-kr/azure/ai-services/speech-service/
하지만, local에서 분명히 잘됐음에도 불구하고, Docker로 띄워서 클라우드 서버에 올리니깐 아래와 같은 오류가 계속 발생했다.
Could not initialize class com.microsoft.cognitiveservices.speech.SpeechConfig
이유를 전혀 모르겠어서 한참 해맸다. 결론은 SDK 설치 설명서 안에 있었다.
위와 같이 Alpine Linux는 Debian 환경으로 만들어주는 작업이 필요했다. 우리 Spring의 Base Image가 eclipse-temurin:17-jdk:alpine이었다. 그래서 작동이 안됐던 것이다. 기존 DockerFile은 이랬다.
FROM eclipse-temurin:17-jdk-alpine AS build
WORKDIR /workspace/app
COPY . /workspace/app
RUN chmod +x ./gradlew
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean bootJar
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*-SNAPSHOT.jar)
FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/build/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
RUN apk add tzdata
ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.capstone.CapstoneApplication"]
그래서 base image를 alpine이 아닌걸로 바꿨다. 그런데 또 다른 문제가 발생했다. 참고로 Spring을 왜 이렇게 Build했는지에 대해서 궁금하면 Spring Multistaging Build 이 글에 내가 작성해놨으니 이거 봐주면 좋겠다.
설명서를 잘 보면, Ubuntu 22.04는 기본값이 OpenSSL 3.0인데, 이는 지원하지 않는다고 한다. 불행이도, eclipse-temurin:17-jdk는 Ubuntu 22.04이다. (제일 안정된 버전으로 가져오기 때문임) 따라서, Open SSL 1.1 버전을 까는 과정이 필요했다. 그래서 기존 DockerFile을 수정했다.
FROM eclipse-temurin:17-jdk AS download
WORKDIR /workspace/app
RUN wget http://www.openssl.org/source/openssl-1.1.1.tar.gz
FROM eclipse-temurin:17-jdk AS build
WORKDIR /workspace/app
COPY --from=download /workspace/app/openssl-1.1.1.tar.gz .
RUN apt-get update
RUN apt-get install -y tzdata build-essential ca-certificates libasound2 wget
RUN tar -xzvf openssl-1.1.1.tar.gz \
&& cd openssl-1.1.1 \
&& ./config \
&& make \
&& make install \
&& ldconfig
COPY . /workspace/app
RUN chmod +x ./gradlew
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean bootJar
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*-SNAPSHOT.jar)
FROM eclipse-temurin:17-jdk
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/build/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.example.capstone.CapstoneApplication"]
SDK에서 기본으로 요구하는 패캐지들은 아래와 같다.
sudo apt-get update
sudo apt-get install build-essential libssl-dev ca-certificates libasound2 wget
여기서, libssl-dev만 wget을 통해서 따로 받아왔다. 그랬더니, SpeechConfig 오류 현상은 해결됐다.
하지만, 이제 다른 오류가 발생했다. 전부다 0점이 나왔다. 이유를 찾아야한다.
https://learn.microsoft.com/ko-kr/azure/ai-services/speech-service/how-to-use-logging
위에 글을 보면, Speech SDK를 로깅하는 방법이 나와있다. 그래서, 로그를 한번 출력해보니...
[856528]: 212ms SPX_TRACE_ERROR: AZ_LOG_ERROR: tlsio_openssl.c:691 error:1416F086:SSL
routines:tls_process_server_certificate:certificate verify failed
[856528]: 212ms SPX_TRACE_ERROR: AZ_LOG_ERROR: tlsio_openssl.c:2464 FORCE-Closing
tlsio instance.
[856528]: 212ms SPX_TRACE_SCOPE_ENTER: uws_web_socket.cpp:247 OnWebSocketOpened
[856528]: 212ms SPX_TRACE_ERROR: web_socket.cpp:907 WS open operation failed with
result=1(WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED), code=2573[0x00000a0d],
time=2024-05-01T10:38:42.8680426Z
[856528]: 212ms SPX_TRACE_INFO: usp_connection.cpp:933 TS:151, TransportError:
connection:0x34021870, code=5, string=Connection failed (no connection to the remote host).
Internal error: 1. Error details: Failed with error: WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED
wss://koreacentral.stt.speech.microsoft.com/speech/universal/v2
X-ConnectionId: 51c962ed10cc4e2bb07a9591eb582f6e
[856528]: 212ms SPX_TRACE_ERROR: usp_reco_engine_adapter.cpp:2009 Response: On Error:
Code:5, Message: Connection failed (no connection to the remote host). Internal error: 1.
Error details: Failed with error: WS_OPEN_ERROR_UNDERLYING_IO_OPEN_FAILED
ssl 인증서 오류가 나서 Socket 통신이 진행되고 있지 않았다... 처음에는 통신이 안되니깐 방화벽 인바운드/아웃바운드 규칙 때문인줄 알았다. (AWS EC2에 올려서 사용중이기 때문에...) 그런데 확인을 해보니깐 이 부분은 전혀 문제가 없었다. 그래서 혹시 openssl이 제대로 설치가 안됐나..? 확인해보았다.
docker exec {container_name} openssl version
위 명령어를 통해 컨테이너 내부의 openssl version을 체크해보니, 3.0이 나오는 것이었다. 즉, open ssl 1.1.1이 제대로 설치되지 않았다는 것이다. 그래서, Docker File을 제정비 했다.
FROM eclipse-temurin:17-jdk AS download
WORKDIR /workspace/app
RUN wget https://www.openssl.org/source/openssl-1.1.1o.tar.gz
FROM eclipse-temurin:17-jdk AS build
WORKDIR /workspace/app
RUN apt-get update && apt-get remove -y openssl && apt-get install -y perl libfindbin-libs-perl build-essential zlib1g-dev
COPY --from=download /workspace/app/openssl-1.1.1o.tar.gz .
RUN tar -zxvf openssl-1.1.1o.tar.gz
WORKDIR /workspace/app/openssl-1.1.1o
RUN ./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared zlib
RUN make && make install
RUN apt-get update && apt-get install -y tzdata ca-certificates
COPY . /workspace/app
WORKDIR /workspace/app
RUN chmod +x ./gradlew
RUN --mount=type=cache,target=/root/.gradle ./gradlew clean bootJar
RUN mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*-SNAPSHOT.jar)
FROM eclipse-temurin:17-jdk
VOLUME /tmp
COPY --from=build /usr/local/ssl /usr/local/ssl
ARG DEPENDENCY=/workspace/app/build/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENV PATH="/usr/local/ssl/bin:$PATH"
ENV LD_LIBRARY_PATH="/usr/local/ssl/lib:$LD_LIBRARY_PATH"
ENV SSL_CERT_DIR "/etc/ssl/certs"
ENTRYPOINT ["java", "-cp", "app:app/lib/*", "com.example.capstone.CapstoneApplication"]
Stackoveflow를 뒤지면서 oepn ssl을 다운그레이드 하는 법을 엄청 찾았다.
또한, Azure Speech Git Repo Issue를 하나하나 뒤져보았다.
https://github.com/Azure-Samples/cognitive-services-speech-sdk/issues/2276
이 글에서 참고하여 위에 같이 DockerFile을 재구성했고
정상적으로 결과가 나왔다!!! 몇일 밤새면서 겨우 고쳤다...
추후, 해당 API를 이용하여 개발하시는 분들을 위하여... 나처럼 고생하지 말라고 글을 써봤다.
'BackEnd > 배포' 카테고리의 다른 글
[배포] Route 53 + Nginx + Certbot으로 Https 적용하기 (0) | 2024.06.23 |
---|---|
[배포] "외국민" 서비스 배포 과정 - (1) (0) | 2024.05.04 |
[배포] Docker로 Ruby On Rails 배포하기 (0) | 2024.05.03 |
[배포] Docker로 Spring 서버 배포하기 (1) | 2024.04.07 |