모듈 4: Docker를 사용하여 Google App Engine에서 Cloud Run으로 마이그레이션

이 Codelab 시리즈(사용자 주도형, 실무 가이드)는 Google App Engine(표준) 개발자가 일련의 마이그레이션을 통해 자신의 앱을 현대화할 수 있도록 돕기 위한 것입니다. 이렇게 하면 사용자는 Cloud Run, App Engine 에 대한 Google Cloud의 컨테이너 호스팅 자매 서비스, 기타 컨테이너 호스팅 서비스에 앱을 컨테이너화하여 더 쉽게 이동하도록 할 수 있습니다.

이 가이드에서는 컨테이너에서 애플리케이션을 개발, 제공, 실행하는 데 널리 사용되는 플랫폼인 Docker를 사용하여 Cloud Run 완전 관리형 서비스에 배포할 App Engine 앱을 컨테이너화하는 방법을 설명합니다. Python 2 개발자라면 이 가이드에서 모듈 2 Cloud NDB App Engine 샘플 앱을 시작하며 Python 3 개발자는 모듈 3 Cloud Datastore 샘플을 사용하여 시작합니다.

학습 목표

  • Docker를 사용하여 앱 컨테이너화
  • Cloud Run에 컨테이너 이미지 배포

필요한 사항

설문조사

이 Codelab을 어떻게 사용할 예정인가요?

읽기만 할 계획입니다. 읽은 다음 연습 활동을 완료할 계획입니다.

App Engine 및 Cloud Functions와 같은 PaaS 시스템은 팀과 애플리케이션에 많은 편의성을 제공합니다. 예를 들어 이러한 서버리스 플랫폼을 사용하면 SysAdmin/Devops에서 솔루션 빌드에 집중할 수 있습니다. 필요에 따라 앱을 자동 확장하고, 사용한 만큼만 지불하는 결제 도구로 0까지 축소할 수 있으며, 다양한 개발 언어를 사용할 수 있습니다.

그러나 컨테이너의 유연성 또한 임의의 언어, 라이브러리, 바이너리 등을 선택할 수 있습니다. 두 가지 방법의 장점을 모두 활용하여 서버리스의 유연성과 컨테이너의 편의성을 제공하는 것이 Google Cloud Run의 핵심입니다.

Cloud Run 사용 방법을 배우는 것은 Cloud Run 문서에서 다루는 이 Codelab의 범위에 포함되지 않습니다. 여기서 목표는 Cloud Run(또는 기타 서비스)용 App Engine 앱을 컨테이너화하는 방법을 알아보는 것입니다. 계속하기 전에 알아두어야 할 몇 가지 사항이 있는데, 일단 애플리케이션 코드를 가져와 배포하지 않게 되면 사용자 환경이 약간 달라지고 수준이 좀더 낮아집니다.

대신 컨테이너를 빌드하고 배포하는 방법과 같은 컨테이너에 대한 항목을 알아야 합니다. 또한 App Engine의 웹 서버를 더 이상 사용하지 않을 것이므로 웹 서버를 포함하여 컨테이너 이미지에 넣을 항목을 결정해야 합니다. 이 경로를 따르지 않으려면 App Engine에 앱을 보관하는 것은 나쁘지 않습니다.

이 가이드에서는 App Engine 구성 파일을 컨테이너 구성으로 대체하고 앱을 컨테이너로 결정한 후 앱 시작 방법을 지정하는 방법을 알아봅니다. 이 항목 중 대부분은 App Engine에서 자동으로 처리됩니다.

이 마이그레이션에는 다음 단계가 포함됩니다.

  1. 설정/사전 작업
  2. 애플리케이션 컨테이너화
    • 구성 파일 교체
    • 애플리케이션 파일 수정

이 가이드의 주요 부분을 진행하기 전에 프로젝트를 설정하고 코드를 가져온 후 기본 앱을 배포하여 작동하는 코드로 시작할 수 있도록 준비합니다.

1. 프로젝트 설정

모듈 2 또는 모듈 3 Codelab을 완료했으면 동일 프로젝트(및 코드)를 다시 사용하는 것이 좋습니다. 또는 완전히 새로운 프로젝트를 만들거나 다른 기존 프로젝트를 다시 사용할 수도 있습니다. 프로젝트에 활성 결제 계정이 있고 App Engine(앱)이 사용 설정되어 있는지 확인합니다.

2. 기준 샘플 앱 가져오기

이 Codelab의 기본 요건 중 하나는 작동하는 모듈 2 또는 모듈 3 샘플 앱을 준비하는 것입니다. 샘플 앱이 없는 경우에는 계속하기 전에 아래 가이드(위 링크)를 완료하세요. 가이드 내용을 잘 알고 계시다면 아래 모듈 2 또는 3 코드를 선택하여 시작하세요.

그 코드가 사용자의 것이든 Google의 것이든 관계없이 이 가이드의 Python 2 버전은 모듈 2 코드에서 시작하고, 마찬가지로 Python 3 버전은 모듈 3 코드에서 시작합니다. 이 모듈 4 Codelab은 각 단계를 안내합니다. 선택 사항에 따라 다르지만, 완료되면 모듈 4 저장소 폴더 중 하나(완료)와 비슷한 코드를 사용해야 합니다.

Python 2 모듈 2 시작 파일(사용자 또는 Google의 파일)의 디렉터리는 다음과 같습니다.

$ ls
README.md               appengine_config.py     requirements.txt
app.yaml                main.py                 templates

사용자 본인의 모듈 2(2.x) 코드를 사용하는 경우 lib 폴더도 생성됩니다. Python 3에는 libappengine_config.py도 사용되지 않으며 모듈 3(3.x) 시작 코드는 다음과 같습니다.

$ ls
README.md               main.py                 templates
app.yaml                requirements.txt

3. 기준 앱 (재)배포

이제 남은 사전 작업 실행 단계는 다음과 같습니다.

  1. gcloud 명령줄 도구 다시 숙지
  2. gcloud app deploy를 사용하여 샘플 앱 다시 배포
  3. 앱이 문제 없이 App Engine에서 실행되는지 확인합니다.

위 단계를 성공적으로 실행하면 컨테이너화할 준비가 된 것입니다.

Docker는 오늘날 업계에서 표준 컨테이너화 플랫폼입니다. 앞에서 언급한 것처럼, 문제는 컨테이너 이미지를 빌드하는 방법을 결정하는 구성 파일인 효율적인 Dockerfile를 선별하려면 노력이 필요하다는 점입니다. 반면 Buildpacks는 점검 도구를 사용하여 앱의 종속 항목을 판별하므로 앱에서 Buildpacks 컨테이너의 효율을 최대한 높일 수 있습니다.

컨테이너 및 Docker를 이미 알고 있고 Cloud Run용 App Engine 앱의 컨테이너화에 대해 자세히 알고 싶은 경우라면 제대로 오셨습니다. 나중에 모듈 5 Codelab(Cloud Buildpack과 동일)도 수행합니다. Google의 베어본 샘플 앱은 앞서 언급한 Dockerfile 문제의 일부를 방지할 만큼 가볍습니다.

마이그레이션 단계에는 App Engine 구성 파일을 교체하고 앱을 시작할 방법을 지정하는 단계가 포함됩니다. 아래는 각 플랫폼 유형에 대해 예상되는 구성 파일을 요약한 표입니다. App Engine 열과 Docker 열(선택사항)을 비교합니다.

설명

App Engine

Docker

Buildpacks

일반 구성

app.yaml

Dockerfile

(service.yaml)

타사 라이브러리

requirements.txt

requirements.txt

requirements.txt

타사 구성

app.yaml(+ appengine_config.pylib[2.x-only])

(해당 없음)

(해당 없음)

시작

(해당 없음) 또는 app.yaml(entrypoint가 사용된 경우)

Dockerfile

Procfile

파일 무시

.gcloudignore, .gitignore

.gcloudignore, .gitignore, .dockerignore

.gcloudignore, .gitignore

앱을 컨테이너화하면 Cloud Run에 배포할 수 있습니다. 다른 Google Cloud 컨테이너 플랫폼 옵션에는 Compute Engine, GKE, Anthos가 있습니다.

일반 구성

App Engine에서 마이그레이션하는 것은 컨테이너 빌드 및 실행 방법을 간략하게 설명하는 Dockerfileapp.yaml을 대체하는 것을 의미합니다. App Engine은 자동으로 애플리케이션을 시작하지만 Cloud Run은 시작하지 않습니다. 이것이 Dockerfile ENTRYPOINTCMD 명령어의 용도입니다. 이 Cloud Run 문서 페이지에서 Dockerfile에 대해 자세히 알아보고 gunicorn을 생성하는 예시 Dockerfile을 참조하세요.

Dockerfile에서 ENTRYPOINT 또는 CMD를 사용하는 대신 Procfile을 사용하는 방법도 있습니다. 마지막으로 .dockerignore를 사용하면 앱 이외의 파일을 필터링하여 컨테이너 크기를 줄이는 데 도움이 됩니다. 더 많은 내용이 추가될 예정입니다.

app.yaml을 삭제하고 Dockerfile 만들기

app.yaml은 컨테이너에서 사용되지 않으므로 지금 삭제하세요. 컨테이너 구성 파일은 Dockerfile이며 샘플 앱에는 최소 1개만 필요합니다. 사용 중인 Python 버전에 따라 이 콘텐츠로 Dockerfile을 만들고 NNN2 또는 3으로 바꿉니다.

FROM python:NNN-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
ENTRYPOINT ["python", "main.py"]

대부분의 Dockerfile은 컨테이너를 만드는 방법을 지정하지만, 예외적으로 ENTRYPOINT는 컨테이너를 시작하는 방법을 지정하고 이 경우 python main.py를 호출하여 Flask 개발 서버를 실행합니다. Docker를 처음 사용하는 경우 FROM 지시문은 시작할 기본 이미지를 나타내고, 'slim'은 최소 Python 분산을 나타냅니다. Docker Python 이미지 페이지에서 자세히 알아보세요.

중간 명령어 집합은 작업 디렉터리(/app)를 만들고 애플리케이션 파일을 복사한 다음 pip install을 실행하여 타사 라이브러리를 컨테이너에 가져옵니다. WORKDIR은 Linux mkdir 명령어와 cd 명령어를 함께 결합합니다. 자세한 내용은 WORKDIR 문서 를 참조하세요. COPYRUN 지시문에는 설명이 필요 없습니다.

타사 라이브러리

requirements.txt 파일은 동일하게 유지될 수 있습니다. Flask가 Datastore 클라이언트 라이브러리(Cloud Datastore 또는 Cloud NDB)와 함께 있어야 합니다. 이 문서 작성 당시의 현재 버전은 20.0.4이며 Gunicorn과 같은 여타의 WSGI 호환 HTTP 서버를 사용하려는 경우 gunicorn==20.0.4requirements.txt에 추가합니다.

타사 구성

Python 2 App Engine 개발자는 타사 라이브러리를 lib 폴더에 복사하고 requirements.txt에서 참조하고 app.yaml에서 항목별로 구분하며 appengine_config.py로 지원한다는 것을 알고 있습니다. Python 3 App Engine 앱과 같은 컨테이너는 requirements.txt만 사용하므로 다른 모든 것은 삭제할 수 있습니다. 즉, 2.x App Engine 앱이 있는 경우 이제 appengine_config.py와 모든 lib 폴더를 삭제하세요.

시작

Python 2 사용자는 App Engine의 웹 서버를 시작하지 않지만 컨테이너로 이동할 때 이 작업을 수행해야 합니다. 앱 시작 방법을 지정하는 DockerfileCMD 또는 ENTRYPOINT 지시문을 추가하면 됩니다. 이 방법은 Python 3 사용자를 위해 아래 동일한 방식으로 설명되어 있습니다.

Python 3 사용자는 app.yaml 파일을 변환하여 handlers 섹션에서 script: auto 지시문 대신 entrypoint를 가져올 수 있습니다. Python 3 app.yaml에서 entrypoint를 사용하는 경우 다음과 같이 표시됩니다.

runtime: python38
entrypoint: python main.py

entrypoint 지시문은 서버를 시작하는 방법을 App Engine에 알려줍니다. 거의 바로 Dockerfile(또는 Buildpacks를 사용하여 앱을 컨테이너화하는 경우에는 Procfile[모듈 5 참조])에 옮길 수 있습니다. 두 플랫폼 간에 진입점 지시문이 이동하는 위치를 요약합니다.

  • Docker: Dockerfile의 줄: ENTRYPOINT ["python", "main.py"]
  • Buildpacks: Procfile의 줄: web: python main.py

Flask 개발 서버를 사용하는 경우 테스트에는 문제가 없지만 애플리케이션에 gunicorn과 같은 프로덕션 서버를 사용하는 경우 Cloud Run 빠른 시작 샘플에서처럼 ENTRYPOINT 또는 CMD 지시문을 지정해야 합니다.

파일 무시

다음과 같이 .dockerignore 파일을 만들어 컨테이너 크기를 잘라내며 컨테이너 이미지가 다음과 같은 불필요한 파일이 있는 것처럼 보이지 않도록 하는 것이 좋습니다.

*.md
*.pyc
*.pyo
.git/
.gitignore
__pycache__

애플리케이션 파일

모든 모듈 2 또는 모듈 3 앱은 Python 2~3와 완전히 호환되므로 main.py의 핵심 구성요소가 변경되지 않습니다. 다음 몇 줄의 시작 코드만 추가됩니다. Cloud Run에서 앱을 호출할 수 있으려면 포트 8080이 열려 있어야 하므로 개발 서버를 시작할 수 있도록 main.py 하단에 줄 한 쌍을 추가합니다.

if __name__ == '__main__':
    import os
    app.run(debug=True, threaded=True, host='0.0.0.0',
            port=int(os.environ.get('PORT', 8080)))

Docker 구성 및 소스 파일 업데이트가 완료되면 Cloud Run에서 실행할 수 있습니다. 그 전에 서비스에 관해 간단하게 살펴보겠습니다.

서비스 및 앱

App Engine은 애플리케이션을 호스팅하기 위해 만들어졌지만 마이크로서비스 모음으로 구성된 웹 서비스 또는 애플리케이션을 호스팅하는 플랫폼이기도 합니다. Cloud Run에서 모든 것이 실제 서비스이든 또는 웹 인터페이스가 있는 애플리케이션이든 서비스 복제가 아니라 서비스이므로, 애플리케이션이 아니라 서비스 배포로 사용합니다.

App Engine 앱이 여러 서비스로 구성되어 있지 않으면 사실 애플리케이션을 배포할 때 어떠한 종류의 이름 지정도 할 필요가 없습니다. Cloud Run을 사용하면 서비스 이름이 있어야 합니다. 반면 App Engine의 appspot.com 도메인에는 프로젝트 ID(예: https://PROJECT_ID.appspot.com)와 리전 ID 약어(예: http://PROJECT_ID.REGION_ID.r.appspot.com)가 있습니다.

하지만 Cloud Run 서비스의 도메인에는 서비스 이름, 리전 ID 약어, 해시가 있지만 프로젝트 ID(예: https://SVC_NAME-HASH-REG_ABBR.a.run.app)는 없습니다. 결론적으로, 서비스 이름을 생각해 보세요.

서비스 배포

아래 명령어를 실행하여 컨테이너 이미지를 빌드하고 Cloud Run에 배포합니다. 메시지가 표시되면 리전을 선택하고 인증되지 않은 연결을 허용하고 더 간편한 테스트를 위해 리전을 선택합니다. 여기서 SVC_NAME은 배포하려는 서비스의 이름입니다.

$ gcloud beta run deploy SVC_NAME --source .
Please choose a target platform:
 [1] Cloud Run (fully managed)
 [2] Cloud Run for Anthos deployed on Google Cloud
 [3] Cloud Run for Anthos deployed on VMware
 [4] cancel
Please enter your numeric choice:  1

To specify the platform yourself, pass `--platform managed`. Or, to make this the default target platform, run `gcloud config set run/platform managed`.

Please specify a region:
 [1] asia-east1
 [2] asia-east2
 [3] asia-northeast1
 [4] asia-northeast2
 [5] asia-northeast3
 [6] asia-south1
 [7] asia-southeast1
 [8] asia-southeast2
 [9] australia-southeast1
 [10] europe-north1
 [11] europe-west1
 [12] europe-west2
 [13] europe-west3
 [14] europe-west4
 [15] europe-west6
 [16] northamerica-northeast1
 [17] southamerica-east1
 [18] us-central1
 [19] us-east1
 [20] us-east4
 [21] us-west1
 [22] us-west2
 [23] us-west3
 [24] us-west4
 [25] cancel
Please enter your numeric choice: <select your numeric region choice>

To make this the default region, run `gcloud config set run/region REGION`.

Allow unauthenticated invocations to [SVC_NAME] (y/N)?  y

Building using Dockerfile and deploying container to Cloud Run service [SVC_NAME] in project [PROJECT_ID] region [REGION]
✓ Building and deploying new service... Done.
  ✓ Uploading sources...
  ✓ Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/BUILD-HASH?project=PROJECT_NUM].
  ✓ Creating Revision... Deploying Revision.
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Done.
Service [SVC_NAME] revision [SVC_NAME-00001-vos] has been deployed and is serving 100 percent of traffic.
Service URL: https://SVC_NAME-HASH-REG_ABBR.a.run.app

브라우저로 지정된 URL을 방문하여 배포가 성공했는지 확인합니다.

gcloud 명령어가 나타내는 것처럼 사용자는 다양한 기본 설정을 지정하여 출력과 상호작용을 줄일 수 있습니다. 예를 들어 모든 상호작용을 방지하려면 다음과 같은 한 줄의 배포 명령을 대신 사용할 수 있습니다.

$ gcloud beta run deploy SVC_NAME --source . --platform managed --region REGION --allow-unauthenticated

이 명령을 사용할 경우에는 위에서 설명한 대로 색인 생성 메뉴 선택이 아닌, 동일한 서비스 이름 SVC_NAME 및 원하는 REGION 이름을 선택해야 합니다.

앱이 App Engine에서처럼 Cloud Run에서 작동하는지 확인합니다. 앞의 Codelab을 수행하지 않고 이 시리즈를 바로 시작한 경우에는 앱 자체가 변경되지 않습니다. 모든 방문을 기본 웹페이지(/)에 등록하고 사이트를 충분히 방문한 후 다음과 같이 표시됩니다.

visitme 앱

이제 코드는 2.x이든 3.x이든 상관없이 모듈 4 저장소 폴더에 있는 파일과 일치합니다. 이 모듈 4 Codelab을 완료하셨습니다.

선택사항: 삭제

다음 마이그레이션 Codelab으로 이동할 준비가 될 때까지 비용이 결제되지 않도록 하려면 삭제를 수행해야 합니다. 현재 다른 제품을 사용하고 있으므로 Cloud Run 가격 책정 가이드를 검토하세요.

선택사항: 서비스 사용 중지

다음 가이드로 이동할 준비가 되지 않았으면 추가 요금이 발생하지 않도록 서비스를 사용 중지합니다. 다음 Codelab으로 이동할 준비가 되었으면 이를 다시 사용 설정하면 됩니다. 앱이 사용 중지되면 비용을 일으키는 트래픽이 수행되지 않습니다. 하지만 무료 할당량을 초과할 경우 해당 Datastore 사용량에 대한 비용이 결제될 수 있습니다. 따라서 제한에 걸리지 않도록 충분히 삭제해야 합니다.

반면에 마이그레이션을 계속하지 않고 모든 것을 완전히 삭제하려면 서비스를 삭제하거나 프로젝트를 완전히 종료합니다.

다음 단계

수고하셨습니다. 앱을 컨테이너화했으므로 이 가이드를 마치겠습니다. 다음 단계는 모듈 5 Codelab(아래 링크)에서 Cloud Buildpacks를 사용하여 같은 작업을 수행하거나 다른 App Engine 마이그레이션을 진행하는 방법입니다.

  • 마이그레이션이 아직인 경우 Python 3으로 마이그레이션합니다. 샘플 앱은 이미 2.x 및 3.x와 호환되므로 Docker 사용자가 Dockerfile을 업데이트하여 Python 3 이미지를 사용할 수 있습니다.
  • 모듈 5: Cloud Buildpacks를 사용하여 Cloud Run으로 마이그레이션
    • Cloud Buildpacks를 사용하여 Cloud Run에서 실행할 앱 컨테이너화
    • Docker, 컨테이너, Dockerfile에 대해 알 필요가 없습니다.
    • 앱이 이미 Python 3로 마이그레이션되어 있어야 합니다.
  • 모듈 7: App Engine push 태스크 큐([push] 태스크 큐를 사용하는 경우 필요)
    • App Engine taskqueue push 태스크를 모듈 1 앱에 추가합니다.
    • 모듈 8에서 Cloud Tasks로 마이그레이션하기 위해 사용자를 준비합니다.
  • 모듈 3:
    • Cloud NDB에서 Cloud Datastore로 Datastore 액세스 현대화
    • Python 3 App Engine 앱 및 비App Engine 앱에 사용되는 라이브러리입니다.
  • 모듈 6: Cloud Firestore로 마이그레이션
    • Cloud Firestore로 마이그레이션하여 Firebase 기능에 액세스
    • Cloud Firestore는 Python 2를 지원하지만 이 Codelab은 Python 3에서만 사용할 수 있습니다.

App Engine 마이그레이션 모듈 Codelab 문제/의견

이 Codelab에 문제가 발견된 경우 문제를 기록하기 전에 먼저 비슷한 기록이 있는지 검색해보세요. 검색 및 새 문제 만들기 링크:

마이그레이션 리소스

모듈 2 및 3(시작) 및 모듈 4(완료)의 저장소 폴더 링크는 아래 표에서 찾을 수 있습니다. 또한 클론 또는 ZIP 파일로 다운로드할 수 있는 모든 App Engine Codelab 마이그레이션 저장소에서 액세스할 수도 있습니다.

Codelab

Python 2

Python 3

모듈 2

코드

(코드)

모듈 3

(코드)

코드

모듈 4

코드

코드

App Engine 및 Cloud Run 리소스

다음은 이 특정 마이그레이션과 관련된 추가적인 리소스입니다.