importerror: /var/task/cryptography/hazmat/bindings/_rust.abi3.so: invalid elf header
zappa를 이용해 장고 프로젝트를 배포한 뒤 데이터베이스에 연결하고 로그인 api를 호출했을 때 위와 같은 에러 메시지가 떴다.
검색해서 이것저것 찾아본 결과 아래와 같은 원인이 있다고 한다.
"Cryptography contains native code and that code is compiled for the architecture (and OS) of the current machine. The AWS lambda documentation currently appears to claim that zipping up your local directory will work, but that's patently untrue. In this case it appears you're running on a Mac, but Lambda needs things compiled as linux ELF shared objects (but also likely needs everything statically linked, etc). You can probably get help with doing that in some AWS Lambda specific forum/mailing list." by reaperhulk
즉, Lambda에는 현재 내가 작업 중인 Mac OS가 아니라 Linux ELF 공유 객체로 컴파일된 항목이 필요하다는 것이다.
이를 해결하기 위한 방법으로는 Mac이나 window의 os에 영향을 받지 않는 docker container를 생성하는 방법이 있다.
lambci에서 다양한 프로그래밍 언어에 대한 lambda 환경을 잘 반영하는 Docker image를 만들어 놓은 것이 있어 이를 이용했다.
아래와 같이 Dockerfile을 작성해 custom docker image를 생성할 수 있다.
[Dockerfile]
FROM lambci/lambda:build-python3.8
# 아래 경로가 efault working directory가 된다.
WORKDIR /var/task
# 디버깅을 위해 port 8000번 expose
EXPOSE 8000
# zappashell에 있음을 알리기 위한 prompt
RUN echo 'export PS1="\[\e[36m\]zappashell>\[\e[m\] "' >> /root/.bashrc
CMD ["bash"]
아래와 같이 이미지를 생성한다.
docker build -t zappa-docker-image .
그 다음 Docker image로 쉽게 이동할 수 있는 바로 가기 스크립트(.sh 파일)를 만든 뒤 이 안에 몇 가지 매개변수를 더 추가할 추가하면 미리 설정해 놓은 AWS 자격 증명을 활용하는 것 역시 가능하다.
[zappashell.sh]
docker run -ti -p 8000:8000 -e AWS_PROFILE=zappa -v "$(pwd):/var/task" -v ~/.aws/:/root/.aws --rm zappa-docker-image
그럼 이제 아래와 같이 스크립트를 실행하면 현재 작업 디렉토리가 Docker 인스턴스에 매핑되고, lambda의 경우 모든 사용자의 코드는 기본 실행 디렉토리인 /var/task에 마운트 된다.
아래와 같이 현재 디렉토리를 확인해 보면 /var/task인 것을 확인할 수 있다.
$ source zappashell.sh
zappashell >>>
zappashell >>> pwd
/var/task
그러면 이제 도커 인스턴스로 생성된 shell 안에서 가상환경을 실행한 후(나의 경우는 pipenv shell) -> zappa init -> zappa deploy 등등의 배포 과정을 거치면 배포가 완료 된다~!
zappashell >>> pipenv shell
zappashell >>> zappa init
...
참고
Guide to using Django with Zappa
Serverless Django with Zappa