imhamburger 님의 블로그

Amazon ECR 이미지 빌드하기 (Feat. Lambda) 본문

도커(Docker)

Amazon ECR 이미지 빌드하기 (Feat. Lambda)

imhamburger 2025. 6. 7. 21:50

현재 회사에서는 Amazon ECR을 사용하여 도커 이미지를 관리하고 있다.

추천공고 모델 코드도 도커 이미지로 만들어 ECR에 저장하고 이 이미지는 lambda 에서 실행한다.

이 Lambda 함수는 에어플로우를 통해 주기적으로 호출되어 모델이 자동으로 학습되고 업데이트되는 배치 작업이 수행된다.

 

Amazon ECR의 도커 이미지는 S3에 저장된 코드를 기반으로 자동으로 업데이트되도록 설정되어 있다. 하지만 S3에 새로운 코드를 업로드했음에도, 도커 이미지에 변경 사항이 반영되지 않는 문제가 발생했다.

 

에러메세지

Not found: Dataset xxxx:data_mart was not found in location xxxx

 

그래서 디버깅을 하기위해 AWS ECR에서 이미지를 받아 로컬에서 테스트를 해보았다.

이미지를 받는건 docker pull 명령어와 비슷하다.

docker pull {AWS 계정 ID}.dkr.ecr.{region}.amazonaws.com/{이미지 경로}

 

이미지를 받기위해선 내가 사용하고 있는 계정이 ecr에 로그인 되어있어야 한다.

aws ecr get-login-password --region {입력}\
| docker login --username AWS\
--password-stdin {계정ID}.dkr.ecr.{region}.amazonaws.com

 

이미지를 받아 run 해보니 내가 업데이트한 코드가 반영되지 않아 있었다.

그래서...... 다시 이미지를 빌드해야했다.

 

이미지를 빌드하고 Amazon ECR에 이미지를 올리기 위해선 당연히 Dockerfile이 필요하다.

그런데..... 예전에 썼던 Dockerfile이 남아있지않아... 새롭게 작성해야 했다.

 

Dockerfile

FROM public.ecr.aws/lambda/python:3.10

# Copy install scripts
COPY requirements.txt /opt/
COPY key_config.json /var/task/

RUN pip install --upgrade pip -q

RUN pip install -r /opt/requirements.txt -q
RUN yum update -y && yum install -y libgomp

COPY train_model.py utils.py /var/task/
CMD [ "train_model.lambda_handler" ]

 

  • 이미지는 파이썬 버전 10을 사용해야했다. requirements 에 10 버전 미만은 실행되지 않는 모듈이 있었다.
  • 필요한 key 파일, 코드파일도 /var/task 라는 폴더 안에 복사해야 한다.
  • 그리고 필요한 의존성들을 설치하고 lambda에서 실행될거라 cmd는 [실행할 파일명.lambda_handler(함수명)] 으로 입력한다.

도커파일을 만들면서 여러가지 에러를 만났다.

 

 

에러메세지 1: apt-get: command not found

apt-get 명령이 없다는 건, 이미지 기반 OS가 Ubuntu/Debian 계열이 아니다라는 뜻이다.

 

해결방법: OS 확인

cat /etc/os-release
OS 유형 패키지 매니저 vim 설치 명령
Ubuntu / Debian apt-get apt-get update && apt-get install -y vim
Alpine Linux apk apk add --no-cache vim
CentOS / RHEL yum yum install -y vim
Amazon Linux yum yum install -y vim

 

 

에러메세지 2: exec format error

"errorMessage":"RequestId: ... Error: fork/exec /usr/local/bin/python: exec format error"

 

이건 "exec format error", 즉 Lambda가 컨테이너를 실행하려다 실패한 경우이다.

AWS Lambda는 기본적으로 Linux x86_64 (amd64) 또는 arm64 환경에서 동작한다.
하지만 내가 빌드한 Docker 이미지가 Mac용 (darwin/arm64 또는 darwin/amd64) 이라면, Lambda에서는 실행할 수 없다.

 

그래서 로컬에서 도커 이미지를 빌드할 때 --platform을 추가하여 빌드해야 한다.

docker build --platform linux/amd64 -t <your-ecr-repo>:latest .

 

 

그리고 Lambda는 일반 Python 베이스 이미지를 지원하지 않아 AWS Lambda용 Python 3.10 베이스 이미지를 사용해야 한다.

FROM public.ecr.aws/lambda/python:3.10

 

 

에러메세지 3: Unable to import module 'train_model': No module named 'pandas'

 'Payload': '{"errorMessage": "Unable to import module \'train_model\': No module named \'pandas\'", "errorType": "Runtime.ImportModuleError", "requestId": "", "stackTrace": []}'})

 

이건 내가 의존성 설치를 안해서 생긴 에러이기 때문에 requirements에 추가하여 설치하였다.

 

 

에러메세지 4: Unable to import module 'train_model': No module named 'train_model'

 'Payload': '{"errorMessage": "Unable to import module \'train_model\': No module named \'train_model\'", "errorType": "Runtime.ImportModuleError", "requestId": "", "stackTrace": []}'})

 

이 에러는 처음에 Lambda 콘솔이나 Airflow에서 호출 시 핸들러를 train_model.lambda_handler 이렇게 정확히 설정을 안해서 그런줄 알았는데 Lambda에서 파일을 실행하려면 파일경로는 /app 이 아니라 WORKDIR을 /var/task로 맞춰야 했다.

 

그럼 왜 Lambda 컨테이너 내 기본 작업 디렉토리가 /var/task인가?

AWS Lambda 런타임이 컨테이너나 환경을 띄울 때,

함수 코드가 자동으로 /var/task 디렉토리에 복사되고 그 위치를 기준으로 핸들러 모듈을 찾도록 설계되어 있다.

  • Lambda 함수가 실행될 때, 핸들러 모듈은 /var/task에서 찾음
  • 만약 다른 경로에 있으면, 핸들러를 못 찾아서 No module named '...' 오류가 난다.

 

에러메세지 4: Unable to import module 'train_model': libgomp.so.1: cannot open shared object file: No such file or directory

'Payload': '{"errorMessage": "Unable to import module \'train_model\': libgomp.so.1: cannot open shared object file: No such file or directory", "errorType": "Runtime.ImportModuleError", "requestId": "", "stackTrace": []}'})

libgomp.so.1는 GNU OpenMP 라이브러리이다.

보통 pandas, numpy, scikit-learn 같은 패키지들이 내부적으로 병렬처리용으로 OpenMP를 사용할 때 필요하다.

 

따라서 Docker 이미지에 libgomp.so.1 라이브러리가 없어서 Lambda에서 train_model 모듈 임포트 시, 내부 종속성에서 이 라이브러리를 찾지 못해 에러가 발생한 것이다.

 

그래서 dockerfile에 다음과 같이 추가해주었다.

RUN yum install -y libgomp

 

ECR에 이미지가 정상적으로 올라갔다면 Lambda 에서 이미지 URI를 새로 올린 이미지로 바꿔주면 끝이다!

이렇게하여 모든 에러를 해결하고 에어플로우가 정상적으로 작동할 수 있게되었따아아

 

Amazon ECR은 전에 프로젝트 때 써본적이 없어서 처음엔 당황스러웠는데 차근차근 알아보니 도커 허브랑 같은 기능을 할 뿐이고.. 명령어도 똑같아서 금방 해결할 수 있었다.