왜 시작인 docker container 라고 생각하는 사람이 있을 것 같다. 결론부터 말하자면 파이썬 외부 라이브러리를 이용하기 위해서 이다. requests, pillow 같은 라이브러리는 python 설치시 같이 포함되는 기본 라이브러리가 아니다. 이러한 라이브러를 이용하기 위한 가장 정석적인 방법이 docker를 이용하는 방법이다. AWS Lambda 가 사용하는 docker image 를 개발 PC에서 실행시켜 해당 환경을 docker container에서 동작시켜 파이썬 라이브러리를 특정 경로에 설치하고 이를 zip 로 만들어서 aws lambda 에 업로드 하는 방법이다.
(이것외에 남이 만든 zip 파일을 이용하는 방법도 있는 것 같다. 그런 것을 원한다면 https://github.com/keithrozario/Klayers?tab=readme-ov-file 에서 찾아 보길 바란다. 다만 내가 원하는 라이브러리가 존재하지 않을 수도 있다. )
딱히 docker 명령어에 대해 자세히 설명하지 않겠다. 이번에 처음으로 docker를 실무에 이용해봤지 나는 docker 사용에 익숙하지 못하다. 따라서 내가 docker에 대해 설명하는 것은 틀릴 수 있다. 그리고 docker 는 설치되어 있다고 가정하고 진행하겠다.
AWS Lambda가 사용하는 docker 이미지에 대한 정보는 https://gallery.ecr.aws/lambda/python 에서 찾을 수 있다. 이렇게 만들어진 docker 이미지는 AWS 에서만든 linux 배포판을 기반으로 만들어졌다. 여기에 대한 정보는 https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-image.html 에서 확인 할 수 있다. 내가 사용하려는 python3.11 은 Amazon Linux 2 을 기반으로 한다. python3.12 부터는 Amazon Linux 2023 을 기반으로 한다.
Amazon Linux 2 은 redhat 을 기반으로 한 것 같다. (yum 을 이용해서 패키지를 설치한다. yum 은 ubuntu 에서의 apt 같은 것이다.)
내 경우는 python3.11 이기 때문에 public.ecr.aws/lambda/python:3.11 을 다운받았다. 아래 과정은 docker 이미지를 설치컨테이너를 실행하는 명령어 이다.
AWS Lambda 에 맞는 docker container 다운로드 및 설정
# 다운로드
docker pull public.ecr.aws/lambda/python:3.11
# 다운로드 확인
docker images
# 컨테이너 생성
# 시작 command 를 /bin/bash 로 변경하면서 생성한다.
docker create -i --name aws_py_311 public.ecr.aws/lambda/python:3.11 /bin/bash
# 컨테이너 실행
docker start aws_py_311
# 컨테이너 접속
docker exec -it aws_py_311 /bin/bash
# 컨테이너 빠져나오기
exit
위에서 시작 command 를 변경하는 것이 있는데, 이것이 좀 중요하다. 기본적으로 생성되는 docker container 가 파이썬 특정 경로의 lambda_handler 를 실행하는 것으로 설정되어 있다. 이것을 변경하지 않고 docker conainer 를 실행하면 그냥 에러를 내면서 종료되어 버린다.
docker container 에 필요 파이썬 라이브러리 설치
이제 aws lambda 를 개발할 때 필요한 파이썬 라이브러리를 설치해보겠다. 그런데 이 파이썬 라이브러리를 특정 경로에 설치해야 한다. 그리고 이 파일들을 zip 파일로 만들어야 한다.
cd ~
mkdir python
cd python
# /root/python 디렉토리에 파이썬 라이브러리 설치
pip3.11 install requests -t .
pip3.11 install boto3 -t .
# pillow-simd 가 아닌 pillow 를 설치하려면
pip3.11 install pillow -t .
# zip 프로그램 설치
yum install zip
# python.zip 으로 압축
cd ..
zip -r python.zip python/
컨테이너 안의 파일을 다운받기 위해서는 container shell 이 아닌 내 개발 PC의 shell 에서
docker cp aws_py_311:/root/python.zip .
하면 된다.
pillow-simd 를 설치하는 경우
pillow-simd 를 이용하는 경우 좀 복잡하다. 이 경우 컴파일이 필요하다. 그리고 추가적인 리눅스 패키지를 다운받아야 한다. 그리고 설치한 리눅스 패키지 때문에 shared library(so 파일, 윈도우로 치면 dll 같은 것)을 같이 zip 에 포함해야 한다.
내 개인적인 경험으로 pillow 보다 pillow-simd 를 사용하면 40%는 빨라지는 것 같다. pillow-simd 는 인텔 CPU의 avx2 명령어를 사용한다. 따라서 x86 전용이다. https://github.com/uploadcare/pillow-simd/issues/43 이 이슈가 open 상태인 것으로 보아 arm 은 지원하지 않는것 같다.
내가 오늘 기준으로 컴파일 해봤을 때 pillow-simd==v8.4.0.post0 버전만 사용이 가능했다. 어째든 다음 과정을 거치면 된다.
# pillow-simd 컴파일 준비
yum install -y \
freetype-devel \
gcc \
ghostscript \
lcms2-devel \
libffi-devel \
libimagequant-devel \
libjpeg-devel \
libraqm-devel \
libtiff-devel \
libwebp-devel \
make \
openjpeg2-devel \
rh-python311 \
rh-python311-python-virtualenv \
sudo \
tcl-devel \
tk-devel \
tkinter \
which \
xorg-x11-server-Xvfb \
zlib-devel \
&& yum clean all
# 디렉토리에 파이썬 라이브러리 설치
cd ~
mkdir python
cd python
# pillow-simd 컴파일, 최신 버전은 에러가 발생했음
CC="cc -mavx2" pip install -U --force-reinstall -t . --compile pillow-simd==v8.4.0.post0
# shared library 한 곳에 모우기
# /root/python/lib에 필요한 파일을 모운다.
mkdir lib
cp /usr/lib64/libtiff.so.5 lib/libtiff.so.5
cp /usr/lib64/libjpeg.so.62 lib/libjpeg.so.62
cp /usr/lib64/libjbig.so.2.0 lib/libjbig.so.2.0
cp /usr/lib64/libopenjp2.so.7 lib/libopenjp2.so.7
cp /usr/lib64/libxcb.so.1 lib/libxcb.so.1
cp /usr/lib64/liblcms2.so.2 lib/liblcms2.so.2
cp /usr/lib64/libpng15.so.15 lib/libpng15.so.15
cp /usr/lib64/libwebp.so.4 lib/libwebp.so.4
cp /usr/lib64/libwebpmux.so.0 lib/libwebpmux.so.0
# zip 프로그램 설치
yum install zip
# python.zip 으로 압축
cd ..
zip -r python.zip python/
python 버전이 다르거나 다른 pillow-simd 버전을 사용하는 경우 다른 so 파일로 변경될 수 있다. 이 경우
AWS Lambda로 thumbnail 만들기(3) - 트러블 슈팅
를 참고해서 어떤 파일의 so 파일이 필요한지 확인하기 바란다.
이 경우도 동일하게 아래처럼 python.zip 파일을 내 개발 PC로 옮길 수 있다.
docker cp aws_py_311:/root/python.zip .
다음에는 AWS lambda 를 설정하는 방법을 설명하겠다.