얼쑤의 녹음 분석 API를 Docker 이미지로 만들었습니다. 이미지 안에서 root로 실행한 테스트는 통과했고, 기본 실행 명령으로 서버도 떴습니다. 그런데 기본 계정으로 뜬 서버에 처음 녹음 분석을 요청하자 HTTP 500이 돌아왔습니다. 로그에는 RuntimeError가 남았습니다. 서버가 요청을 받을 수 있게 된 시점과 실제로 분석 코드를 불러오는 시점 사이에 차이가 있었습니다.
모듈을 불러올 때 필요한 Numba 캐시
분석에 쓰는 librosa에는 Numba가 JIT 컴파일하고 결과를 캐시하는 함수가 있습니다. 이번에는 분석 요청에서 관련 모듈을 불러올 때 Numba가 캐시 위치를 찾지 못해 cannot cache function … no locator available 오류를 냈습니다. 요청 전체를 보내지 않고 같은 이미지에서 import librosa.core.notation만 실행해도 이 오류를 확인할 수 있었습니다.
이미지의 기본 실행 사용자는 숫자 UID 10001이었습니다. 그 이미지에는 이 UID에 해당하는 사용자 항목이 없어서 실행 중 확인한 HOME은 /였습니다. 해당 계정으로는 패키지가 들어 있는 디렉터리와 홈 아래 캐시 위치에 쓸 수 없었습니다. 앞선 테스트는 root로 실행했으므로, 기본 계정이 마주치는 쓰기 권한 조건을 재현할 수 없었습니다.
캐시에 쓰기 가능한 위치 지정
실행 계정은 그대로 두고, Numba가 쓸 경로를 /tmp 아래로 지정했습니다.
ENV NUMBA_CACHE_DIR=/tmp/numba-cache
USER 10001:10001
같은 이미지와 실행 계정에서 NUMBA_CACHE_DIR을 비우면 모듈을 불러올 때 같은 오류가 났고, 이미지의 캐시 경로 설정을 사용하면 import가 통과했습니다. 분석 API도 경로를 비우면 첫 호출에서 HTTP 500을 반환했습니다. 운영 Compose에서는 루트 파일시스템을 읽기 전용으로 두고, 녹음 임시 파일과 Numba 캐시가 쓰는 /tmp에 쓰기 가능한 tmpfs를 붙였습니다. docker inspect로 ReadonlyRootfs=true를 확인했습니다. 512MiB는 tmpfs에 설정한 상한입니다. 실제 캐시 사용량이나 운영 첫 요청의 처리 시간은 이 확인으로 알 수 없습니다.
새 컨테이너의 첫 분석 요청 검증
Apple Silicon 개발 노트북에서 캐시 경로를 지정한 Linux ARM64 이미지를 띄웠습니다. 외부로 연결되지 않는 Docker 내부 네트워크에 API와 저장소 대역을 넣고, 호스트에 포트를 열지 않은 상태에서 컨테이너 안으로 요청을 보냈습니다. 기본 실행 계정으로 합성 녹음 한 건을 분석한 결과는 HTTP 200과 DONE이었습니다. API 로그에 기록된 처리 시간은 3.282초였습니다. 저장소 대역이 없는 조건에서는 HTTP 502와 DOWNLOAD_FAILED가 나와, 다운로드가 실패한 경우도 구분할 수 있었습니다.
이미지를 다시 빌드한 직후의 첫 실행에서 같은 500이 한 번 더 나왔습니다. 같은 이미지로 여러 번 다시 띄웠을 때는 재현되지 않았습니다. 여러 첫 요청이 같은 캐시에 접근할 때도 문제가 생기는지 보기 위해 새 API 컨테이너 다섯 개를 띄우고, 컨테이너마다 첫 요청 묶음 여덟 건을 동시에 보냈습니다. 40건 모두 HTTP 200과 DONE이었고 해당 실행에서 오류 로그는 0건이었습니다. 한 차례 재발한 500의 원인은 확인하지 못했습니다.
이 검증에서 확인한 것은 개발 노트북의 ARM64 실행 이미지가 기본 계정으로 합성 녹음을 받아 분석까지 마치는 경로입니다. 운영 서버에서의 지연 시간과 실제 연주의 채점 품질은 별도의 검증 범위입니다. 같은 이미지에서 확인한 Python과 FFmpeg 버전은 이미지 구성 글에 정리했습니다. FFmpeg를 유지하며 Python 3.12로 맞추기

댓글
댓글과 반응은 GitHub 계정으로 로그인해 남길 수 있어요.