자습서: 서비스 커넥터를 사용하여 Postgres on Azure App Service로 Django 앱 빌드
참고 항목
이 자습서에서는 서비스 커넥터를 사용하여 웹앱을 데이터베이스 서비스에 연결합니다. 이 자습서는 App Service 자습서를 수정한 것이므로 몇 가지 유사성을 볼 수 있습니다. App Service 자습서에서 제공된 연결 프로세스를 서비스 커넥터가 활용되고 간소화하는 방법을 알아보려면 Postgres 데이터베이스에 대한 암호 없는 커넥터 만들기 섹션을 살펴봅니다.
이 자습서에서는 데이터 기반 Python Django 웹앱을 Azure App Service에 배포하고 Azure Database for PostgreSQL 유연한 서버 데이터베이스에 연결하는 방법을 보여 줍니다.
이 자습서에서는 Azure CLI를 사용하여 다음 작업을 완료합니다.
- Python 및 Azure CLI를 사용하여 초기 환경 설정
- Azure Database for PostgreSQL 유연한 서버 데이터베이스 만들기
- Azure App Service에 코드 배포 및 PostgreSQL 유연한 서버에 연결
- 코드 업데이트 및 다시 배포
- 진단 로그 보기
- Azure Portal에서 웹앱 관리
초기 환경 설정
Azure Portal의 Azure Cloud Shell에서 시작하고 Azure CLI에 대한 서비스 커넥터 암호 없는 확장을 설치합니다.
az extension add --name serviceconnector-passwordless --upgrade
샘플 앱 복제 또는 다운로드
샘플 리포지토리를 복제합니다.
git clone https://github.com/Azure-Samples/serviceconnector-webapp-postgresql-django-passwordless.git
다음 폴더로 이동합니다.
cd serviceconnector-webapp-postgresql-django-passwordless
이 자습서에서는 Django 웹앱을 Azure App Service에 배포합니다. 웹앱은 Azure 역할 기반 액세스 제어를 사용하여 시스템이 할당한 관리 ID(암호 없는 연결)를 사용하여 Azure Storage 및 Azure Database for PostgreSQL - 유연한 서버 리소스에 액세스합니다. 이 코드는 Python용 Azure ID 클라이언트 라이브러리의 DefaultAzureCredential 클래스를 사용합니다. DefaultAzureCredential
클래스는 App Service에 대한 관리 ID가 있는지 자동으로 검색하고 이를 사용하여 다른 Azure 리소스에 액세스합니다.
- 프로덕션 설정은 azuresite/production.py 파일에 있습니다. 개발 설정은 azuresite/settings.py에 있습니다.
WEBSITE_HOSTNAME
환경 변수가 설정되면 앱에서 프로덕션 설정을 사용합니다. Azure App Service는 자동으로 이 변수를 웹앱의 URL로 설정합니다(예:msdocs-django.azurewebsites.net
).
프로덕션 설정은 모든 프로덕션 환경에서 실행되도록 Django를 구성하는 것과 관련이 있으며 App Service에만 국한되지 않습니다. 자세한 내용은 Django 배포 검사 목록을 참조하세요. 또한 일부 변경 내용에 대한 자세한 내용은 Azure의 Django에 대한 프로덕션 설정을 참조하세요.
문제가 있나요? 알려주세요.
Azure에서 Postgres 데이터베이스 만들기
자습서에 필요한 환경 변수를 설정합니다.
LOCATION="eastus" RAND_ID=$RANDOM RESOURCE_GROUP_NAME="msdocs-mi-web-app" APP_SERVICE_NAME="msdocs-mi-web-$RAND_ID" DB_SERVER_NAME="msdocs-mi-postgres-$RAND_ID" ADMIN_USER="demoadmin" ADMIN_PW="{your database password}"
Important
ADMIN_PW
는 다음 세 가지 범주에서 8~128자를 포함해야 합니다. 영문 대문자, 영문 소문자, 숫자 및 영숫자가 아닌 문자 사용자 이름 또는 암호를 만들 때$
문자를 사용하지 않습니다. 나중에 Python 앱을 실행하는 데 사용되는 Linux 컨테이너 내에서$
문자가 특정 의미를 갖는 이러한 값을 사용하여 환경 변수를 만듭니다.리소스 그룹을 만듭니다(원하는 경우 이름을 변경할 수 있음). 리소스 그룹 이름은 캐시되고 후속 명령에 자동으로 적용됩니다.
az group create --name $RESOURCE_GROUP_NAME --location $LOCATION
데이터베이스 서버를 만듭니다. 현재 클라이언트 IP 주소에 대한 액세스를 사용하도록 설정할지 묻는 메시지가 표시되면
y
를 입력합니다. 이 프로세스는 몇 분이 소요됩니다.az postgres flexible-server create \ --resource-group $RESOURCE_GROUP_NAME \ --name $DB_SERVER_NAME \ --location $LOCATION \ --admin-user $ADMIN_USER \ --admin-password $ADMIN_PW \ --sku-name Standard_D2ds_v4 --active-directory-auth Enabled
az
명령이 인식되지 않는 경우 초기 환경 설정에서 설명한 대로 Azure CLI가 설치되어 있는지 확인합니다.az postgres flexible-server create 명령은 다음 작업을 수행합니다. 이 작업은 몇 분 정도 걸립니다.
- 캐시된 이름이 아직 없는 경우 기본 리소스 그룹을 만듭니다.
- PostgreSQL 유연한 서버를 만듭니다.
--name
매개 변수로 지정된 서버 이름입니다. Azure의 모든 이름은 고유해야 합니다.--sku-name
매개 변수로 지정된 sku를 사용합니다.
--admin-user
및--admin-password
매개 변수로 지정된 사용자 이름과 암호로 관리자 계정을 만듭니다.--database-name
매개 변수로 지정된 이름의 데이터베이스를 만듭니다.
az postgres flexible-server firewall-rule create 명령을 사용하여 서버에서 방화벽 규칙을 구성합니다. 이 규칙은 로컬 환경에서 서버에 액세스할 수 있도록 허용합니다. (이전 단계에서 클라이언트 IP 주소에서 액세스를 허용하라는 메시지가 표시되면 이 단계를 건너뛸 수 있습니다.)
IP_ADDRESS=<your IP> az postgres flexible-server firewall-rule create \ --resource-group $RESOURCE_GROUP_NAME \ --name $DB_SERVER_NAME \ --rule-name AllowMyIP \ --start-ip-address $IP_ADDRESS \ --end-ip-address $IP_ADDRESS
IP 주소를 보여 주는 도구나 웹 사이트를 사용하여 명령에서
<your IP>
를 대체합니다. 예를 들어, 내 IP 주소는 무엇인가요? 웹 사이트를 사용할 수 있습니다.az postgres flexible-server execute 명령을 사용하여
restaurant
라는 이름의 데이터베이스를 만듭니다.az postgres flexible-server execute \ --name $DB_SERVER_NAME \ --admin-user $ADMIN_USER \ --admin-password $ADMIN_PW \ --database-name postgres \ --querytext 'create database restaurant;'
Azure App Service에 코드 배포
이 섹션에서는 App Service 앱에서 앱 호스트를 만들고, 이 앱을 Postgres 데이터베이스에 연결한 다음, 코드를 해당 호스트에 배포합니다.
App Service 앱 만들기
터미널에서 앱 코드가 포함된 serviceconnector-webapp-postgresql-django-passwordless 리포지토리 폴더에 있는지 확인합니다.
다음
az webapp up
명령을 실행하여 앱에 대한 App Service 호스트를 만듭니다.az webapp up \ --resource-group $RESOURCE_GROUP_NAME \ --location $LOCATION \ --name $APP_SERVICE_NAME \ --runtime PYTHON:3.9 \ --sku B1
sku는 App Service 요금제의 크기(CPU, 메모리)와 비용을 정의합니다. B1(기본) 서비스 계획은 Azure 구독에 소액의 비용이 발생합니다. App Service 요금제의 전체 목록은 App Service 가격 책정 페이지를 참조하세요.
이 명령은 이전
az group create
명령에서 캐시된 리소스 그룹 및 위치(이 예제에서는eastus
지역에 있는 그룹$RESOURCE_GROUP_NAME
)를 사용하여 다음 작업을 수행합니다. 이 작업에는 몇 분 정도 걸릴 수 있습니다.- 기본 가격 책정 계층(B1)에서 App Service 플랜을 만듭니다.
--sku
를 생략하여 기본값을 사용할 수 있습니다. - App Service 앱을 만듭니다.
- 앱에 대해 기본 로깅을 사용하도록 설정합니다.
- 빌드 자동화를 사용하도록 설정된 ZIP 배포를 사용하여 리포지토리를 업로드합니다.
- 기본 가격 책정 계층(B1)에서 App Service 플랜을 만듭니다.
az webapp config set 명령으로 리포지토리의 start.sh를 사용하도록 App Service를 구성합니다.
az webapp config set \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --startup-file "start.sh"
Postgres 데이터베이스에 대한 암호 없는 커넥터 만들기
이제 코드가 App Service에 배포되면 다음 단계는 Azure에서 앱을 Postgres 데이터베이스에 연결하는 것입니다. 앱 코드는 PostgresSQL 유연한 서버에 대한 AZURE_POSTGRESQL_CONNECTIONSTRING
이라는 환경 변수와 Azure Storage 계정에 대한 AZURE_STORAGEBLOB_RESOURCEENDPOINT
라는 환경 변수에서 데이터베이스 정보를 찾을 것으로 예상합니다.
서비스 커넥터 명령은 관리 ID와 Azure 역할 기반 액세스 제어를 사용하도록 Azure Storage 및 Azure Database for PostgreSQL 리소스를 구성합니다. 이러한 명령은 웹앱을 이러한 리소스에 연결하는 App Service의 앱 설정을 만듭니다. 명령의 출력에는 암호 없이도 기능을 사용할 수 있도록 하기 위해 수행된 서비스 커넥터 작업이 나열됩니다.
- az webapp connection create postgres-flexible 명령을 사용하여 PostgreSQL 서비스 커넥터를 추가합니다. 시스템이 할당한 관리 ID는 웹앱을 대상 리소스(이 경우 PostgreSQL)에 인증하는 데 사용됩니다.
az webapp connection create postgres-flexible \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --target-resource-group $RESOURCE_GROUP_NAME \ --server $DB_SERVER_NAME \ --database restaurant \ --client-type python \ --system-identity
참고 항목
"구독이 Microsoft.ServiceLinker를 사용하도록 등록되어 있지 않습니다."라는 오류 메시지가 표시되면 az provider register -n Microsoft.ServiceLinker
를 실행하여 Service Connector 리소스 공급자를 등록하고 연결 명령을 다시 실행합니다.
Python 코드에서 os.environ.get('AZURE_POSTGRESQL_HOST')
과 같은 명령문을 사용하여 이러한 설정을 환경 변수로 액세스합니다. 자세한 내용은 환경 변수 액세스를 참조하세요.
문제가 있나요? 먼저 문제 해결 가이드를 참조하세요. 그렇지 않으면 알려주세요.
스토리지 계정 만들기 및 연결
- az webapp connection create storage-blob 명령을 사용하여 스토리지 계정을 만들고 다음 구성을 수행하는 서비스 커넥터를 만듭니다.
웹앱에서 시스템이 할당한 관리 ID 사용
새로 만들어진 스토리지 계정에 Storage Blob 데이터 기여자 역할이 있는 웹앱을 추가합니다.
웹앱에서 액세스를 허용하도록 스토리지 계정 네트워크를 구성합니다.
STORAGE_ACCOUNT_URL=$(az webapp connection create storage-blob \ --new true \ --resource-group $RESOURCE_GROUP_NAME \ --name $APP_SERVICE_NAME \ --target-resource-group $RESOURCE_GROUP_NAME \ --client-type python \ --system-identity \ --query configurations[].value \ --output tsv) STORAGE_ACCOUNT_NAME=$(cut -d . -f1 <<< $(cut -d / -f3 <<< $STORAGE_ACCOUNT_URL))
레스토랑 앱 사용자가 이미지에 액세스할 수 있도록 Blob 공용 액세스를 허용하도록 스토리지 계정을 업데이트합니다.
az storage account update \ --name $STORAGE_ACCOUNT_NAME \ --allow-blob-public-access
az storage container create 명령을 사용하여 스토리지 계정에
photos
라는 컨테이너를 만듭니다. 새로 만들어진 컨테이너의 Blob에 대한 익명의 읽기(공용) 액세스를 허용합니다.# Set the BLOB_ENDPOINT variable BLOB_ENDPOINT=$(az storage account show --name $STORAGE_ACCOUNT_NAME --query "primaryEndpoints.blob" | sed 's/"//g') echo $BLOB_ENDPOINT # Create the storage container using the BLOB_ENDPOINT variable az storage container create \ --account-name $STORAGE_ACCOUNT_NAME \ --name photos \ --public-access blob \ --auth-mode login \ --blob-endpoint $BLOB_ENDPOINT
Azure에서 Python 웹앱 테스트
샘플 Python 앱은 azure.identity 패키지와 해당 DefaultAzureCredential
클래스를 사용합니다. 앱이 Azure에서 실행되는 경우 DefaultAzureCredential
은 App Service에 대한 관리 ID가 있는지 자동으로 검색하고, 있다면 해당 ID를 사용하여 다른 Azure 리소스(이 경우 스토리지 및 PostgreSQL)에 액세스합니다. 이러한 리소스에 액세스하기 위해 App Service에 스토리지 키, 인증서 또는 자격 증명을 제공할 필요가 없습니다.
URL
http://$APP_SERVICE_NAME.azurewebsites.net
에서 배포된 애플리케이션을 찾습니다.앱이 시작되려면 1~2분 정도 걸릴 수 있습니다. 기본 샘플 앱 페이지가 아닌 기본 앱 페이지가 표시되면 잠시 기다렸다가 브라우저를 새로 고칩니다.
레스토랑을 추가하고 레스토랑에 대한 사진이 있는 검토를 추가하여 샘플 앱의 기능을 테스트해 보세요. 레스토랑 및 검토 정보는 Azure Database for PostgreSQL에 저장되고 사진은 Azure Storage에 저장됩니다. 다음은 스크린샷의 예입니다.
리소스 정리
앱을 유지하거나 추가 자습서를 계속하려면 다음 단계로 건너뛰세요. 그렇지 않으면 요금이 지속적으로 청구되지 않도록 이 자습서에서 만든 리소스 그룹을 삭제합니다.
az group delete --name $RESOURCE_GROUP_NAME --no-wait
리소스 그룹을 삭제하면 해당 그룹에 포함된 모든 리소스도 할당 취소되고 삭제됩니다. 이 명령을 사용하기 전에 해당 그룹의 리소스가 더 이상 필요하지 않은지 확인하세요.
모든 리소스를 삭제하는 데 시간이 걸릴 수 있습니다. --no-wait
인수를 사용하면 명령이 즉시 반환됩니다.
문제가 있나요? 알려주세요.