Azure App Service용 Linux Python 앱 구성

이 문서에서는 Azure App Service에서 Python 앱을 실행하는 방법, 기존 앱을 Azure로 마이그레이션하는 방법 및 필요한 경우 App Service의 동작을 사용자 지정하는 방법에 대해 설명합니다. Python 앱을 배포할 때 모든 필수 pip 모듈을 함께 배포해야 합니다.

사용자가 pip install -r requirements.txtGit 리포지토리 또는 빌드 자동화가 설정된zip 패키지를 배포하면 App Service 배포 엔진이 자동으로 가상 환경을 활성화하고 를 실행합니다.

이 가이드에서는 App Service의 기본 제공 Linux 컨테이너를 사용하는 Python 개발자를 위한 주요 개념과 지침을 제공합니다. Azure App Service를 사용한 경험이 없는 경우 먼저 Python 빠른 시작PostgreSQL을 사용하는 Python 자습서를 수행해야 합니다.

다음과 같이 Azure Portal 또는 Azure CLI를 사용하여 구성할 수 있습니다.

  • Azure Portal: Azure Portal에서 App Service 앱 구성의 설명에 따라 앱의 설정>구성 페이지를 사용합니다.

  • Azure CLI: 다음과 같은 두 가지 옵션이 있습니다.

    • Azure Cloud Shell에서 명령을 실행합니다.
    • 최신 버전의 Azure CLI를 설치하여 명령을 로컬로 실행한 다음, az login을 사용하여 Azure에 로그인합니다.

참고 항목

Linux는 App Service에서 Python 앱을 실행하는 유일한 운영 체제 옵션입니다. Windows의 Python은 더 이상 지원되지 않습니다. 그러나 사용자 지정 Windows 컨테이너 이미지를 직접 빌드하여 App Service에서 실행할 수 있습니다. 자세한 내용은 사용자 지정 Docker 이미지 사용을 참조하세요

Python 버전 구성

  • Azure Portal: Linux 컨테이너의 일반 설정 구성에 설명된 대로 구성 페이지의 일반 설정 탭을 사용합니다.

  • Azure CLI:

    • az webapp config show 명령을 사용하여 현재 Python 버전을 표시합니다.

      az webapp config show --resource-group <resource-group-name> --name <app-name> --query linuxFxVersion
      

      <resource-group-name><app-name>을 웹앱에 적합한 이름으로 바꿉니다.

    • az webapp config set 명령을 사용하여 Python 버전을 설정합니다.

      az webapp config set --resource-group <resource-group-name> --name <app-name> --linux-fx-version "PYTHON|3.11"
      
    • az webapp list-runtimes 명령을 사용하여 Azure App Service에서 지원되는 모든 Python 버전을 표시합니다.

      az webapp list-runtimes --os linux | grep PYTHON
      

사용자 고유의 컨테이너 이미지를 빌드하여 지원되지 않는 Python 버전을 실행할 수도 있습니다. 자세한 내용은 사용자 지정 Docker 이미지 사용을 참조하세요

빌드 자동화 사용자 지정

앱 설정 SCM_DO_BUILD_DURING_DEPLOYMENT1로 설정된 경우 사용자가 앱을 배포하면 Oryx라는 App Service의 빌드 시스템이 다음 단계를 수행합니다.

  1. PRE_BUILD_COMMAND 설정을 통해 지정한 경우 사용자 지정 빌드 전 스크립트를 실행합니다. (스크립트는 다른 Python 및 Node.js 스크립트, pip 및 npm 명령, yarn과 같은 노드 기반 도구(예: yarn installyarn build)를 실행할 수 있습니다.)

  2. pip install -r requirements.txt를 실행합니다. requirements.txt 파일은 프로젝트의 루트 폴더에 있어야 합니다. 그렇지 않으면 빌드 프로세스에서 "setup.py 또는 requirements.txt를 찾을 수 없습니다. pip install을 실행하고 있지 않습니다."라는 오류가 보고됩니다.

  3. 리포지토리의 루트에 manage.py가 있는 경우(Django 앱이라는 의미) manage.py collectstatic을 실행합니다. 그러나 DISABLE_COLLECTSTATIC 설정이 true인 경우 이 단계를 건너뜁니다.

  4. POST_BUILD_COMMAND 설정을 통해 지정한 경우 사용자 지정 빌드 후 스크립트를 실행합니다. (또한, 이 스크립트는 다른 Python 및 Node.js 스크립트, pip 및 npm 명령, 노드 기반 도구를 실행할 수 있습니다.)

기본적으로 PRE_BUILD_COMMAND, POST_BUILD_COMMANDDISABLE_COLLECTSTATIC 설정은 비어 있습니다.

  • Django 앱을 빌드할 때 collectstatic을 실행하지 않도록 설정하려면 DISABLE_COLLECTSTATIC 설정을 true로 설정합니다.

  • 빌드 전 명령을 실행하려면 명령을 포함하도록(예: echo Pre-build command) 또는 프로젝트 루트를 기준으로 하는 스크립트 파일 경로를 포함하도록(예: scripts/prebuild.sh) PRE_BUILD_COMMAND를 설정합니다. 모든 명령은 프로젝트 루트 폴더에 대한 상대 경로를 사용해야 합니다.

  • 빌드 후 명령을 실행하려면 명령을 포함하도록(예: echo Post-build command) 또는 프로젝트 루트를 기준으로 하는 스크립트 파일 경로를 포함하도록(예: scripts/postbuild.sh) POST_BUILD_COMMAND를 설정합니다. 모든 명령은 프로젝트 루트 폴더에 대한 상대 경로를 사용해야 합니다.

빌드 자동화를 사용자 지정하는 추가 설정은 Oryx 구성을 참조하세요.

빌드 및 배포 로그에 액세스하려면 배포 로그 액세스를 참조하세요.

Linux에서 App Service를 실행하고 Python 앱을 빌드하는 방법에 대한 자세한 내용은 Oryx에서 Python 앱을 탐지하고 빌드하는 방법을 참조하세요.

참고 항목

PRE_BUILD_SCRIPT_PATHPOST_BUILD_SCRIPT_PATH 설정은 PRE_BUILD_COMMANDPOST_BUILD_COMMAND와 동일하며 레거시 용도로 지원됩니다.

SCM_DO_BUILD_DURING_DEPLOYMENT 설정은 true 또는 1을 포함하는 경우 배포 중에 Oryx 빌드를 트리거합니다. git, Azure CLI 명령 az webapp up 및 Visual Studio Code를 사용하여 배포하는 경우 이 설정은 true입니다.

참고 항목

Oryx가 실행되는 빌드 컨테이너는 앱이 실행되는 런타임 컨테이너와 다르므로 모든 빌드 전 및 빌드 후 스크립트에서 항상 상대 경로를 사용해야 합니다. 컨테이너 내에서 앱 프로젝트 폴더의 정확한 배치를 사용하지 마세요(예를 들어 site/wwwroot에 배치됨).

기존 애플리케이션을 Azure로 마이그레이션

기존 웹 애플리케이션은 다음과 같이 Azure에 다시 배포할 수 있습니다.

  1. 원본 리포지토리: GitHub와 같은 적절한 리포지토리에서 소스 코드를 유지 관리하여 이 프로세스의 뒷부분에서 지속적인 배포를 설정할 수 있습니다.

    • App Service에서 필요한 패키지를 자동으로 설치하려면 requirements.txt 파일이 리포지토리의 루트에 있어야 합니다.
  2. 데이터베이스: 앱이 데이터베이스를 사용하는 경우 Azure에서도 필요한 리소스를 만듭니다.

  3. App Service 리소스: 애플리케이션을 호스팅하는 리소스 그룹, App Service 요금제 및 App Service 웹앱을 만듭니다. Azure CLI 명령 az webapp up를 실행하여 쉽게 수행할 수 있습니다. 또는 자습서: PostgreSQL을 사용하여 Python(Django 또는 Flask) 웹앱 배포에 표시된 대로 리소스를 만들고 배포할 수 있습니다. 리소스 그룹, App Service 요금제 및 웹앱의 이름을 애플리케이션에 더 적합하도록 바꿉니다.

  4. Environment variables: 애플리케이션에 환경 변수가 필요한 경우 해당하는 App Service 애플리케이션 설정을 만듭니다. 이러한 App Service 설정은 환경 변수 액세스에서 설명한 대로 코드에서 환경 변수로 표시됩니다.

  5. 앱 시작: 이 문서의 뒷부분에 나오는 컨테이너 시작 프로세스 섹션을 검토하여 App Service에서 앱 실행을 시도하는 방법을 이해합니다. App Service는 기본적으로 Gunicorn 웹 서버를 사용하며, 이 서버는 앱 개체 또는 wsgi.py 폴더를 찾을 수 있어야 합니다. 필요한 경우 시작 명령을 사용자 지정할 수 있습니다.

  6. 지속적인 배포: Azure App Service에 대한 지속적인 배포 문서에 설명된 대로 GitHub Actions, Bitbucket 또는 Azure Repos에서 지속적인 배포를 설정합니다. 또는 Azure App Service에 로컬 Git 배포 문서에 설명된 대로 로컬 Git에서 지속적인 배포를 설정합니다.

  7. 사용자 지정 작업: Django 데이터베이스 마이그레이션과 같이 앱을 호스팅하는 App Service 컨테이너 내에서 작업을 수행하려면 SSH를 통해 컨테이너에 연결할 수 있습니다. Django 데이터베이스 마이그레이션을 실행하는 방법에 대한 예제는 자습서: PostgreSQL을 사용하여 Django 웹앱 배포 - 데이터베이스 스키마 생성을 참조하세요.

    • 지속적인 배포를 사용하는 경우 이러한 작업은 앞부분의 빌드 자동화 사용자 지정에서 설명한 대로 빌드 후 명령을 사용하여 수행할 수 있습니다.

이러한 단계가 완료되면 변경 내용을 원본 리포지토리에 커밋하고 해당 업데이트가 App Service에 자동으로 배포되도록 할 수 있습니다.

Django 앱의 프로덕션 설정

Azure App Service와 같은 프로덕션 환경의 경우 Django 앱은 Django의 배포 검사 목록(djangoproject.com)을 따라야 합니다.

다음 표에는 Azure와 관련된 프로덕션 설정이 설명되어 있습니다. 이러한 설정은 앱의 setting.py 파일에서 정의됩니다.

Django 설정 Azure에 대한 지침
SECRET_KEY 환경 변수로 앱 설정에 액세스에 설명된 대로 App Service 설정에 값을 저장합니다. 값을 Azure Key Vault에 "비밀"로 저장할 수도 있습니다.
DEBUG App Service에서 값이 0(false)인 DEBUG 설정을 만든 다음, 해당 값을 환경 변수로 로드합니다. 개발 환경에서 값이 1(true)인 DEBUG 환경 변수를 만듭니다.
ALLOWED_HOSTS Django 앱을 프로덕션 환경에서 사용하려면 settings.pyALLOWED_HOSTS 배열에 앱 URL을 포함해야 합니다. 이 URL은 런타임에 os.environ['WEBSITE_HOSTNAME'] 코드를 사용하여 검색할 수 있습니다. App Service는 자동으로 WEBSITE_HOSTNAME 환경 변수를 앱의 URL로 설정합니다.
DATABASES App Service에서 데이터베이스 연결에 대한 설정을 정의한 다음, 해당 설정을 환경 변수로 로드하여 DATABASES 사전을 채웁니다. 값(특히 사용자 이름 및 암호)을 Azure Key Vault 비밀로 저장할 수도 있습니다.

Django 앱용 정적 파일 제공

Django 웹앱에 정적 프런트 엔드 파일이 포함된 경우 먼저 Django 설명서의 정적 파일 관리에 대한 지침을 따르세요.

App Service의 경우 다음과 같이 수정합니다.

  1. 환경 변수(로컬 개발의 경우) 및 앱 설정(클라우드에 배포하는 경우)을 사용하여 Django STATIC_URLSTATIC_ROOT 변수를 동적으로 설정하는 것이 좋습니다. 예시:

    STATIC_URL = os.environ.get("DJANGO_STATIC_URL", "/static/")
    STATIC_ROOT = os.environ.get("DJANGO_STATIC_ROOT", "./static/")    
    

    DJANGO_STATIC_URLDJANGO_STATIC_ROOT는 로컬 및 클라우드 환경에 따라 변경할 수 있습니다. 예를 들어 정적 파일의 빌드 프로세스에서 파일을 django-static이라는 폴더에 배치하는 경우 기본값을 사용하지 않도록 DJANGO_STATIC_URL/django-static/으로 설정할 수 있습니다.

  2. 다른 폴더에 정적 파일을 생성하는 빌드 전 스크립트가 있는 경우 Django의 collectstatic 프로세스에서 찾을 수 있도록 해당 폴더를 Django STATICFILES_DIRS 변수에 포함합니다. 예를 들어 프런트 엔드 폴더에서 yarn build를 실행하고 yarn에서 정적 파일을 포함하는 build/static 폴더를 생성하는 경우 다음과 같이 해당 폴더를 포함합니다.

    FRONTEND_DIR = "path-to-frontend-folder" 
    STATICFILES_DIRS = [os.path.join(FRONTEND_DIR, 'build', 'static')]    
    

    여기서 FRONTEND_DIR은 yarn과 같은 빌드 도구가 실행되는 경로를 빌드합니다. 원하는 대로 환경 변수 및 앱 설정을 다시 사용할 수 있습니다.

  3. requirements.txt 파일에 whitenoise를 추가합니다. Whitenoise(whitenoise.evans.io)는 프로덕션 Django 앱이 자체 정적 파일을 간편하게 제공할 수 있도록 하는 Python 패키지입니다. Whitenoise는 특히 Django STATIC_ROOT 변수로 지정된 폴더에 있는 파일을 제공합니다.

  4. settings.py 파일에서 Whitenoise에 다음 줄을 추가합니다.

    STATICFILES_STORAGE = ('whitenoise.storage.CompressedManifestStaticFilesStorage')
    
  5. 또한 Whitenoise를 포함하도록 MIDDLEWAREINSTALLED_APPS 목록을 수정합니다.

    MIDDLEWARE = [                                                                   
        'django.middleware.security.SecurityMiddleware',
        # Add whitenoise middleware after the security middleware                             
        'whitenoise.middleware.WhiteNoiseMiddleware',
        # Other values follow
    ]
    
    INSTALLED_APPS = [
        "whitenoise.runserver_nostatic",
        # Other values follow
    ]
    

Flask 앱용 정적 파일 제공

Flask 웹앱에 정적 프런트 엔드 파일이 포함된 경우 먼저 Flask 설명서의 정적 파일 관리 지침을 따릅니다. Flask 애플리케이션에서 정적 파일을 제공하는 예제는 GitHub의 빠른 시작 샘플 Flask 애플리케이션을 참조하세요.

애플리케이션의 경로에서 직접 정적 파일을 제공하려면 send_from_directory 메서드를 사용할 수 있습니다.

from flask import send_from_directory

@app.route('/reports/<path:path>')
def send_report(path):
    return send_from_directory('reports', path)

컨테이너 특성

App Service에 배포된 Python 앱은 App Service Python GitHub 리포지토리에 정의된 Linux Docker 컨테이너 내에서 실행됩니다. 버전별 디렉터리 내에서 이미지 구성을 찾을 수 있습니다.

이 컨테이너에는 다음과 같은 특성이 있습니다.

  • 앱은 --bind=0.0.0.0 --timeout 600 추가 인수를 통해 Gunicorn WSGI HTTP 서버를 사용하여 실행됩니다.

    • 시작 명령을 사용자 지정하여 Gunicorn에 대한 구성 설정을 제공할 수 있습니다.

    • 우발적인 또는 고의적인 DDOS 공격으로부터 웹앱을 보호하기 위해 Gunicorn은 Gunicorn 배포(docs.gunicorn.org)에 설명된 대로 Nginx 역방향 프록시 뒤에서 실행됩니다.

  • 기본적으로 기본 컨테이너 이미지에는 Flask 웹 프레임워크만 포함되지만, 컨테이너는 WSGI 및 Python 3.6 이상과 호환되는 다른 프레임워크(예: Django)를 지원합니다.

  • Django와 같은 다른 패키지를 설치하려면 직접 종속성을 지정하는 프로젝트의 루트에 requirements.txt 파일을 만듭니다. 그러면 프로젝트를 배포할 때 App Service에서 이러한 종속성을 자동으로 설치합니다.

    종속성을 설치하려면 requirements.txt 파일이 반드시 프로젝트 루트에 있어야 합니다. 그렇지 않으면 빌드 프로세스에서 "setup.py 또는 requirements.txt를 찾을 수 없습니다. pip install을 실행하고 있지 않습니다."라는 오류가 보고됩니다. 이 오류가 발생하면 요구 사항 파일의 위치를 확인합니다.

  • App Service는 웹앱의 URL을 사용하여 WEBSITE_HOSTNAME이라는 환경 변수를 자동으로 정의합니다(예: msdocs-hello-world.azurewebsites.net). 또한 앱 이름을 사용하여 WEBSITE_SITE_NAME을 정의합니다(예: msdocs-hello-world).

  • npm 및 Node.js는 컨테이너에 설치되므로 yarn과 같은 노드 기반 빌드 도구를 실행할 수 있습니다.

컨테이너 시작 프로세스

시작하는 동안 Linux의 App Service 컨테이너에서 실행하는 단계는 다음과 같습니다.

  1. 사용자 지정 시작 명령을 사용합니다(제공된 경우).
  2. Django 앱이 있는지 확인하고, 이 앱에 대한 Gunicorn이 탐지되면 시작합니다.
  3. Flask 앱이 있는지 확인하고, 이 앱에 대한 Gunicorn이 탐지되면 시작합니다.
  4. 다른 앱이 없으면 컨테이너에 기본적으로 제공되는 기본 앱을 시작합니다.

다음 섹션에서는 각 옵션에 대한 추가 세부 정보를 제공합니다.

Django 앱

Django 앱의 경우 App Service는 앱 코드 내에서 wsgi.py라는 파일을 찾고, 다음 명령을 사용하여 Gunicorn을 실행합니다.

# <module> is the name of the folder that contains wsgi.py
gunicorn --bind=0.0.0.0 --timeout 600 <module>.wsgi

시작 명령을 보다 구체적으로 제어하려면 사용자 지정 시작 명령을 사용하고, <module>wsgi.py가 포함된 폴더 이름으로 바꾸고, 해당 모듈이 프로젝트 루트에 있지 않은 경우에는 --chdir 인수를 추가합니다. 예를 들어 wsgi.py가 프로젝트 루트의 knboard/backend/config에 있는 경우 --chdir knboard/backend config.wsgi 인수를 사용합니다.

프로덕션 로깅을 사용하려면 사용자 지정 시작 명령에 대한 예제에 표시된 대로 --access-logfile--error-logfile 매개 변수를 추가합니다.

Flask 앱

Flask의 경우 App Service는 application.py 또는 app.py 파일을 찾고, 다음과 같이 Gunicorn을 시작합니다.

# If application.py
gunicorn --bind=0.0.0.0 --timeout 600 application:app

# If app.py
gunicorn --bind=0.0.0.0 --timeout 600 app:app

기본 앱 모듈이 다른 파일에 포함되어 있거나, 앱 개체에 대해 다른 이름을 사용하거나, Gunicorn에 다른 인수를 제공하려면 사용자 지정 시작 명령을 사용합니다.

기본 동작

App Service는 사용자 지정 명령, Django 앱 또는 Flask 앱을 찾지 못하면 다음 그림처럼 opt/defaultsite 폴더에 있는 기본 읽기 전용 앱을 실행합니다.

코드를 배포했는데 여전히 기본 앱이 표시되는 경우 문제 해결 - 앱이 표시되지 않음을 참조하세요.

Screenshot of the default App Service on Linux web page.

마찬가지로 기본 앱 대신 배포한 앱이 표시되는 경우 문제 해결 - 앱이 표시되지 않음을 참조하세요.

시작 명령 사용자 지정

사용자 지정 시작 명령을 제공하거나 시작 명령 파일의 여러 명령을 제공하여 컨테이너의 시작 동작을 제어할 수 있습니다. 시작 명령 파일의 이름은 startup.sh, startup.cmd, startup.txt 등과 같이 원하는 대로 지정할 수 있습니다.

모든 명령은 프로젝트 루트 폴더에 대한 상대 경로를 사용해야 합니다.

시작 명령 또는 명령 파일을 지정하는 방법은 다음과 같습니다.

  • Azure Portal: 앱의 구성 페이지를 선택한 다음, 일반 설정을 선택합니다. 시작 명령 필드에서 시작 명령의 전체 텍스트 또는 시작 명령 파일의 이름을 입력합니다. 그런 다음, 저장을 선택하여 변경 내용을 적용합니다. Linux 컨테이너의 일반 설정 구성을 참조하세요.

  • Azure CLI: az webapp config set 명령과 --startup-file 매개 변수를 사용하여 시작 명령 또는 파일을 설정합니다.

    az webapp config set --resource-group <resource-group-name> --name <app-name> --startup-file "<custom-command>"
    

    <custom-command>를 시작 명령의 전체 텍스트 또는 시작 명령 파일의 이름으로 바꿉니다.

App Service는 사용자 지정 시작 명령 또는 파일을 처리할 때 발생하는 모든 오류를 무시한 다음, Django 및 Flask 앱을 찾아 시작 프로세스를 계속 진행합니다. 예상하는 동작이 발생하지 않는 경우 시작 명령 또는 파일이 오류 없이 작동하고 시작 명령 파일이 앱 코드와 함께 App Service에 배포되었는지 확인합니다. 진단 로그에서 자세한 내용을 확인할 수도 있습니다. 또한 Azure Portal에서 앱의 문제 진단 및 해결 페이지를 확인합니다.

시작 명령 예제

  • 추가된 Gunicorn 인수: 다음 예제에서는 Django 앱을 시작하기 위해 Gunicorn 명령줄에 --workers=4를 추가합니다.

    # <module-path> is the relative path to the folder that contains the module
    # that contains wsgi.py; <module> is the name of the folder containing wsgi.py.
    gunicorn --bind=0.0.0.0 --timeout 600 --workers=4 --chdir <module_path> <module>.wsgi
    

    자세한 내용은 Gunicorn 실행(docs.gunicorn.org)을 참조하세요. 자동 스케일링 규칙을 사용하여 웹앱을 스케일 업 및 스케일 다운하는 경우 시작 명령에서 NUM_CORES 환경 변수를 사용하여 gunicorn 작업자의 수를 동적으로 설정해야 합니다(예: --workers $((($NUM_CORES*2)+1))). 권장되는 gunicorn 작업자 수 설정에 대한 자세한 내용은 Gunicorn FAQ를 참조하세요.

  • Django에 대한 프로덕션 로깅 사용: 명령줄에 --access-logfile '-' 인수 및 --error-logfile '-' 인수를 추가합니다.

    # '-' for the log files means stdout for --access-logfile and stderr for --error-logfile.
    gunicorn --bind=0.0.0.0 --timeout 600 --workers=4 --chdir <module_path> <module>.wsgi --access-logfile '-' --error-logfile '-'
    

    이러한 로그는 App Service 로그 스트림에 표시됩니다.

    자세한 내용은 Gunicorn 로깅(docs.gunicorn.org)을 참조하세요.

  • 사용자 지정 Flask 기본 모듈: 기본적으로 App Service는 Flask 앱의 기본 모듈이 application.py 또는 app.py라고 가정합니다. 기본 모듈이 다른 이름을 사용하는 경우 시작 명령을 사용자 지정해야 합니다. 예를 들어 기본 모듈이 hello.py이고 해당 파일에서 Flask 앱 개체의 이름이 myapp인 Flask 앱이 있는 경우 명령은 다음과 같습니다.

    gunicorn --bind=0.0.0.0 --timeout 600 hello:myapp
    

    기본 모듈이 하위 폴더(예: website)인 경우 --chdir 인수로 이 폴더를 지정합니다.

    gunicorn --bind=0.0.0.0 --timeout 600 --chdir website hello:myapp
    
  • Use a non-Gunicorn server: aiohttp 같은 다른 웹 서버를 사용하려면 다음과 같이 적절한 명령을 시작 명령으로 또는 시작 명령 파일에 사용합니다.

    python3.7 -m aiohttp.web -H localhost -P 8080 package.module:init_func
    

앱 설정에 환경 변수로 액세스

앱 설정은 앱 설정 구성에 설명된 대로 앱을 위한 클라우드에 저장된 값입니다. 이러한 설정은 앱 코드에 환경 변수로 사용할 수 있으며 표준 os.environ 패턴을 사용하여 액세스할 수 있습니다.

예를 들어 DATABASE_SERVER라는 앱 설정을 만든 경우 다음 코드는 해당 설정의 값을 검색합니다.

db_server = os.environ['DATABASE_SERVER']

HTTPS 세션 검색

App Service에서, TLS/SSL 종료(wikipedia.org)는 네트워크 부하 분산 장치에서 발생하므로 모든 HTTPS 요청은 암호화되지 않은 HTTP 요청으로 앱에 도달합니다. 앱 논리에서 사용자 요청의 암호화 여부를 확인해야 하는 경우 X-Forwarded-Proto 헤더를 검사합니다.

if 'X-Forwarded-Proto' in request.headers and request.headers['X-Forwarded-Proto'] == 'https':
# Do something when HTTPS is used

인기 있는 웹 프레임워크를 사용하여 표준 앱 패턴의 X-Forwarded-* 정보에 액세스할 수 있습니다. 예를 들어, Django에서 SECURE_PROXY_SSL_HEADER를 사용하여 Django에 X-Forwarded-Proto 헤더를 사용하도록 지시할 수 있습니다.

진단 로그 액세스

컨테이너 내부에서 생성된 콘솔 로그에 액세스할 수 있습니다.

먼저 다음 명령을 실행하여 컨테이너 로깅을 설정합니다.

az webapp log config --name <app-name> --resource-group <resource-group-name> --docker-container-logging filesystem

<app-name><resource-group-name>을 웹앱에 적합한 이름으로 바꿉니다.

컨테이너 로깅이 설정되면 다음 명령을 실행하여 로그 스트림을 확인합니다.

az webapp log tail --name <app-name> --resource-group <resource-group-name>

콘솔 로그가 즉시 표시되지 않으면 30초 후에 다시 확인합니다.

언제든지 로그 스트리밍을 중지하려면 Ctrl+C를 입력합니다.

https://<app-name>.scm.azurewebsites.net/api/logs/docker의 브라우저에서 로그 파일을 검사할 수도 있습니다.

Azure Portal을 통해 로그에 액세스하려면 앱의 왼쪽 메뉴에서 모니터링>로그 스트림을 선택합니다.

배포 로그 액세스

코드를 배포하면 App Service는 빌드 자동화 사용자 지정 섹션에서 설명한 빌드 프로세스를 수행합니다. 빌드는 자체 컨테이너에서 실행되기 때문에 빌드 로그는 앱의 진단 로그와 별도로 저장됩니다.

다음 단계에 따라 배포 로그에 액세스합니다.

  1. 해당 웹앱의 Azure Portal 왼쪽 메뉴에서 배포>배포 센터를 선택합니다.
  2. 로그 탭에서 가장 최근 커밋의 커밋 ID를 선택합니다.
  3. 나타나는 로그 세부 정보 페이지에서 "oryx 빌드 실행 중..." 옆에 표시되는 로그 표시... 링크를 선택합니다.

requirements.txt의 잘못된 종속성과 같은 빌드 문제와 빌드 전 또는 빌드 후 스크립트의 오류가 이러한 로그에 표시됩니다. 요구 사항 파일의 이름이 정확하게 requirements.txt로 지정되지 않았거나 해당 파일이 프로젝트의 루트 폴더에 표시되지 않는 경우에도 오류가 발생합니다.

브라우저에서 SSH 세션 열기

컨테이너와 직접 SSH 세션을 열려면 앱을 실행해야 합니다.

브라우저에 다음 URL을 붙여넣고 <app-name>을 앱 이름으로 바꿉니다.

https://<app-name>.scm.azurewebsites.net/webssh/host

아직 인증을 받지 못한 경우 연결하기 위해서는 Azure 구독에서 인증을 받아야 합니다. 인증되면 컨테이너 내부에서 명령을 실행할 수 있는 브라우저 내부 셸을 확인합니다.

SSH connection

참고 항목

/home 디렉터리 외부에서 변경한 사항은 컨테이너 자체에 저장되며 앱을 다시 시작한 이후에는 유지되지 않습니다.

로컬 컴퓨터에서 원격 SSH 세션을 열려면 원격 셸에서 SSH 세션 열기를 참조하세요.

SSH 세션에 성공적으로 연결되면 창 아래쪽에 "SSH 연결 설정됨"이라는 메시지가 표시됩니다. "SSH_CONNECTION_CLOSED" 같은 오류가 발생하거나 컨테이너를 다시 시작한다는 메시지가 표시되면 오류 때문에 앱 컨테이너가 시작되지 않을 수 있습니다. 가능한 문제를 조사하는 단계는 문제 해결을 참조하세요.

문제 해결

일반적으로 문제 해결의 첫 번째 단계는 App Service 진단을 사용하는 것입니다.

  1. 해당 웹앱의 Azure Portal 왼쪽 메뉴에서 문제 진단 및 해결을 선택합니다.
  2. 가용성 및 성능을 선택합니다.
  3. 애플리케이션 로그, 컨테이너 충돌컨테이너 문제 옵션의 정보를 검사합니다. 대부분의 일반적인 문제가 여기서 발생합니다.

다음으로 오류 메시지에 대한 배포 로그앱 로그를 검사합니다. 이러한 로그를 검사하여 앱 배포 또는 앱 시작을 방해하는 특정 문제를 파악할 수 있는 경우가 자주 있습니다. 예를 들어 requirements.txt 파일의 이름이 올바르지 않거나 프로젝트 루트 폴더에 없는 경우 빌드가 실패할 수 있습니다.

다음 섹션에서는 특정 문제에 대한 참고 자료를 제공합니다.

앱이 표시되지 않음

  • 사용자 고유의 앱 코드가 배포되면 기본 앱이 표시됩니다. 앱 코드를 App Service에 배포하지 않았거나 App Service에서 앱 코드를 찾지 못하여 기본 앱을 대신 실행했기 때문에 기본 앱이 표시됩니다.

    • App Service를 다시 시작하고, 15-20초 동안 기다린 다음, 앱을 다시 확인합니다.

    • SSH를 사용하여 App Service에 직접 연결하고, 파일이 site/wwwroot에 있는지 확인합니다. 파일이 없으면 다음 단계를 수행합니다.

      1. 값이 1인 SCM_DO_BUILD_DURING_DEPLOYMENT라는 앱 설정을 만들고, 코드를 다시 배포하고, 몇 분 정도 기다렸다가 앱에 다시 액세스를 시도합니다. 앱 설정을 만드는 방법에 대한 자세한 내용은 Azure Portal에서 App Service 앱 구성을 참조하세요.
      2. 배포 프로세스를 검토하고, 배포 로그를 검사하고, 오류를 수정하고, 앱을 다시 배포합니다.
    • 파일이 있으면 App Service에서 특정 시작 파일을 식별하지 못한 것입니다. 앱이 Django 또는 Flask에 대해 예상되는 App Service로 구성되었는지 확인하거나 사용자 지정 시작 명령을 사용합니다.

  • 브라우저에 “서비스를 사용할 수 없음”이라는 메시지가 표시됩니다. App Service가 Gunicorn 서버를 시작했지만 앱 자체는 시작되지 않았음을 나타내는 App Service의 응답을 기다리는 동안 브라우저에서 시간이 초과되었습니다. 이 상태는 Gunicorn 인수가 올바르지 않거나 앱 코드에 오류가 있다는 뜻일 수 있습니다.

    • 특히 App Service 계획에서 가장 낮은 가격 책정 계층을 사용하는 경우 브라우저를 새로 고칩니다. 예를 들어 체험 계층을 사용하는 경우 앱을 시작하는 데 시간이 더 오래 걸릴 수 있으며, 브라우저를 새로 고친 후에 응답하게 됩니다.

    • 앱이 Django 또는 Flask에 대해 예상되는 App Service로 구성되었는지 확인하거나 사용자 지정 시작 명령을 사용합니다.

    • 오류 메시지의 앱 로그 스트림을 검사합니다. 이 로그는 앱 코드의 오류를 보여줍니다.

setup.py 또는 requirements.txt 파일을 찾을 수 없음

  • 로그 스트림에 "setup.py 또는 requirements.txt 찾을 수 없습니다. pip 설치를 실행하지 않음.": Oryx 빌드 프로세스에서 requirements.txt 파일을 찾지 못했습니다.

    • SSH를 통해 웹앱의 컨테이너에 연결하고 requirements.txt 파일의 이름이 올바르게 지정되었으며 site/wwwroot에 있는지 확인합니다. 파일이 없으면 리포지토리에 파일을 만들고 배포에 포함시킵니다. 파일이 별도의 폴더에 있으면 루트로 이동합니다.

앱 시작 시 ModuleNotFoundError

ModuleNotFoundError: No module named 'example' 같은 오류가 표시되는 경우 애플리케이션이 시작될 때 Python에서 하나 이상의 모듈을 찾지 못했음을 의미합니다. 이 오류는 코드를 사용하여 가상 환경을 배포하는 경우에 주로 발생합니다. 가상 환경은 이동할 수 없으므로 애플리케이션 코드를 사용하여 가상 환경을 배포하면 안 됩니다. 대신, 앱 설정 SCM_DO_BUILD_DURING_DEPLOYMENT를 만들고 1로 설정하여 Oryx에서 가상 환경을 만들고 웹앱에 패키지를 설치하도록 합니다. 이 설정은 App Service에 배포할 때마다 Oryx에서 패키지를 강제로 설치합니다. 자세한 내용은 가상 환경 이식성에 대한 이 문서를 참조하세요.

데이터베이스가 잠겼습니다.

Django 앱을 사용하여 데이터베이스 마이그레이션을 실행하려고 할 때 "sqlite3 OperationalError: 데이터베이스가 잠겼습니다."가 표시될 수 있습니다. 이 오류는 애플리케이션이 PostgreSQL for Azure와 같은 클라우드 데이터베이스를 사용하는 대신 기본적으로 Django가 구성된 SQLite 데이터베이스를 사용하고 있음을 나타냅니다.

앱의 settings.py 파일에서 DATABASES 변수를 확인하여 앱이 SQLite 대신 클라우드 데이터베이스를 사용하고 있는지 확인합니다.

자습서: PostgreSQL을 사용하여 Django 웹앱 배포의 샘플에서 이 오류가 발생하는 경우 연결 설정 확인의 단계를 완료했는지 확인합니다.

기타 문제

  • 암호를 입력할 때 SSH 세션에 표시되지 않음: 보안상 이유로 SSH 세션에서는 입력할 때 암호가 숨겨 있습니다. 하지만 문자는 기록되고 있으므로 평소처럼 암호를 입력하고, 입력을 마쳤으면 Enter 키를 누르세요.

  • SSH 세션의 명령이 잘려서 표시됨: 편집기가 자동 줄 바꿈 명령이 아닐 수 있지만 여전히 올바르게 실행됩니다.

  • 정적 자산이 Django 앱에 표시되지 않음: whitenoise 모듈을 사용하도록 설정했는지 확인합니다.

  • "SSL 연결이 필요함" 메시지가 표시됨: 앱 내에서 리소스(예: 데이터베이스)에 액세스하는 데 사용되는 사용자 이름 및 암호를 확인합니다.

추가 리소스