파이썬 - Azure App Service에 응용 프로그램 배포 후의 환경
지난 글에서 Azure App Service의 초기 환경 구성을 살펴봤는데요,
파이썬 - Azure App Service에 응용 프로그램 배포하기 전의 환경
; https://www.sysnet.pe.kr/2/0/13946
그렇다면
파이썬 웹 앱을 배포한 경우에는 어떤 식으로 바뀔까요? ^^
간단하게 예제 프로젝트를 다음과 같이 배포하는 걸 가정해 보겠습니다. 우선, SCM_DO_BUILD_DURING_DEPLOYMENT 설정을 true로 변경하고,
c:\temp> az login
c:\temp> az webapp config appsettings set --resource-group pywebapp_group --name pywebapp --settings SCM_DO_BUILD_DURING_DEPLOYMENT=true
이후 파이썬 (예제) 소스 코드를 압축해 배포합니다.
E:\git_clone> git clone https://github.com/Azure-Samples/msdocs-python-fastapi-webapp-quickstart.git
E:\git_clone> cd msdocs-python-fastapi-webapp-quickstart
E:\git_clone\msdocs-python-fastapi-webapp-quickstart> ucompressarchive test.zip .
E:\git_clone\msdocs-python-fastapi-webapp-quickstart> az webapp deploy --resource-group pywebapp_group --name pywebapp --src-path test.zip
배포가 완료된 후 웹 사이트를 방문해 보면, (기대와는 달리) Azure의 기본 웹 앱이 여전히 실행되고 있습니다. ^^; 단지, 화면의 메시지만 살짝 바뀌었는데요, application.py의 코드에서,
# cat /opt/defaultsite/application.py
from flask import Flask
import os
app = Flask(__name__, static_folder='/opt/defaultsite')
@app.route('/')
def root():
if os.path.isdir('/home/site/deployments') and len(next(os.walk('/home/site/deployments'))[1]) > 1:
return app.send_static_file('hostingstart_dep.html')
else:
return app.send_static_file('hostingstart.html')
(배포로 인해) /home/site/deployments 디렉터리가 생성됐기 때문에 hostingstart_dep.html 페이지가 보이기 때문입니다. 이에 더해 한 가지 변화가 더 있는데요, 배포 후에 SSH 접속을 해보면 "-bash: antenv/bin/activate: No such file or directory" 오류가 발생하지 않고 오히려 파이썬 가상 환경에 진입한 상태의 프롬프트와 함께 시작 디렉터리도 다르게 나옵니다.
((antenv) ) root@pywebapp-532e70cd:/tmp/8dd91f1ff178df3#
당연하겠지만, 배포 후에는 (App Service 인스턴스 구동 후 제일 먼저 실행되는) /opt/startup/startup.sh 파일이 다음과 같이 바뀌었기 때문입니다.
# cat /opt/startup/startup.sh
#!/bin/sh
echo 'export APP_PATH="/tmp/8dd91f1ff178df3"' >> ~/.bashrc
echo 'cd $APP_PATH' >> ~/.bashrc
# Enter the source directory to make sure the script runs where the user expects
cd /tmp/8dd91f1ff178df3
export APP_PATH="/tmp/8dd91f1ff178df3"
if [ -z "$HOST" ]; then
export HOST=0.0.0.0
fi
if [ -z "$PORT" ]; then
export PORT=80
fi
export PATH="/opt/python/3.12.10/bin:${PATH}"
echo 'export VIRTUALENVIRONMENT_PATH="/tmp/8dd91f1ff178df3/antenv"' >> ~/.bashrc
echo '. antenv/bin/activate' >> ~/.bashrc
PYTHON_VERSION=$(python -c "import sys; print(str(sys.version_info.major) + '.' + str(sys.version_info.minor))")
echo Using packages from virtual environment 'antenv' located at '/tmp/8dd91f1ff178df3/antenv'.
export PYTHONPATH=$PYTHONPATH:"/tmp/8dd91f1ff178df3/antenv/lib/python$PYTHON_VERSION/site-packages"
echo "Updated PYTHONPATH to '$PYTHONPATH'"
. antenv/bin/activate
GUNICORN_CMD_ARGS="--timeout 600 --access-logfile '-' --error-logfile '-' -c /opt/startup/gunicorn.conf.py --chdir=/opt/defaultsite" gunicorn application:app
그러니까, Azure App Service에 파이썬 배포를 하면 가상 환경(virtualenv)을 자동으로 구성해 그 내부에, 위의 경우 ""/tmp/8dd91f1ff178df3" 디렉터리 하위에 ZIP 파일의 압축을 해제하는 것입니다.
그런데 문제는, gunicorn을 실행하는 부분에서 application:app을 찾는 디렉터리가 여전히 "--chdir=/opt/defaultsite" 옵션으로 인해 Azure의 기본 웹 앱 디렉터리로 설정돼 있다는 점입니다.
GUNICORN_CMD_ARGS="--timeout 600 --access-logfile '-' --error-logfile '-' -c /opt/startup/gunicorn.conf.py --chdir=/opt/defaultsite"
따라서, 배포 후에 우리가 원하는 웹 앱이 동작하게 만들려면
"Startup Command"를 설정해야 하는 것입니다. (문서에는 "
optional"로 나오지만, 현실적으로는 필수 설정 항목입니다.)
Configure a Linux Python app for Azure App Service
; https://learn.microsoft.com/en-us/azure/app-service/configure-language-python
결국, App Service에 대해서는 (Azure Portal의 콘솔 화면에서 하거나, 또는) 다음과 같이 스크립트 설정 명령을 (자신의 환경에 맞게) 실행해 줘야 합니다.
// msdocs-python-fastapi-webapp-quickstart 예제의 경우라면!
// (지정한 sh 파일은 반드시 LF 형식으로 저장해야 합니다.)
c:\temp> az webapp config set --resource-group pywebapp_group --name pywebapp --startup-file "$APP_PATH/startup.sh"
// 또는, 어차피 현재 디렉터리가 "$APP_PATH"이므로 "./startup.sh"로 대체해도 됩니다.
Azure App Service는 "Startup Command"에 명령어가 있다면 기존의 "/opt/startup/startup.sh"에서 마지막 명령어만 다음과 같은 식으로 대체합니다.
# cat /opt/startup/startup.sh
#!/bin/sh
echo 'export APP_PATH="/tmp/8dd91f1ff178df3"' >> ~/.bashrc
echo 'cd $APP_PATH' >> ~/.bashrc
# ...[생략]...
export PATH="/opt/python/3.12.10/bin:${PATH}"
echo 'export VIRTUALENVIRONMENT_PATH="/tmp/8dd91f1ff178df3/antenv"' >> ~/.bashrc
echo '. antenv/bin/activate' >> ~/.bashrc
PYTHON_VERSION=$(python -c "import sys; print(str(sys.version_info.major) + '.' + str(sys.version_info.minor))")
echo Using packages from virtual environment 'antenv' located at '/tmp/8dd91f1ff178df3/antenv'.
export PYTHONPATH=$PYTHONPATH:"/tmp/8dd91f1ff178df3/antenv/lib/python$PYTHON_VERSION/site-packages"
echo "Updated PYTHONPATH to '$PYTHONPATH'"
. antenv/bin/activate
PATH="$PATH:/tmp/8dd91f1ff178df3" $APP_PATH/startup.sh
이제서야 대충 돌아가는 상황이 정리된 것 같습니다. ^^
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]