재사용 가능한 템플릿으로 Go 앱을 Google Cloud Run에 배포하는 방법과 설정, 환경 변수, 커스텀 도메인, SSL, 배포 시간, 정리 방법을 설명합니다.
몇몇 제 프로젝트는 Google Cloud Run 배포를 처리하기 위해 같은 Makefile과 Dockerfile을 사용합니다. 매번 바퀴를 다시 발명하는 대신, 저는 이것을 GitHub의 재사용 가능한 템플릿으로 묶어 두었습니다: cloud-run-go-deployment. 프로젝트에 넣고, 원하는 AI에게 여러분의 필요에 맞게 조정해 달라고 맡기면, 이미 대부분의 작업이 끝난 셈입니다.
Google Cloud Run은 별다른 복잡한 절차 없이도 말 그대로 약속한 일을 해내는 도구 중 하나입니다. Docker 이미지를 주면 실행합니다. 서버를 관리할 필요도 없고, 스케일링 규칙을 설정할 필요도 없으며, 가용성을 걱정할 필요도 없습니다. 트래픽이 없으면 0까지 스케일다운되므로 사이드 프로젝트를 운영할 때 특히 좋고, 요청이 들어오면 자동으로 스케일업됩니다. 과금은 실제 실행 시간 100ms 단위로 이루어지기 때문에, 트래픽이 적은 앱은 한 달에 1달러도 훨씬 안 되는 비용으로 운영할 수 있습니다.
AWS 같은 서비스와 비교하면, 컨테이너화된 앱을 배포할 때 보통 앞단에 CloudFront나 로드 밸런서를 둔 Lambda 같은 구성이 필요한 반면, Cloud Run은 놀랄 만큼 단순합니다. Docker 이미지를 배포하고, 커스텀 도메인을 연결하고, 무료 SSL 인증서를 받으면 됩니다. 그게 전부입니다. 저는 이 선택의 균형점에 대해 예전에 Polar Bear Blog 글에서 더 자세히 쓴 적이 있습니다. 이것은 제가 Cloud Run 덕분에 자체 호스팅이 현실적으로 느껴졌기 때문에 특별히 만든 가벼운 Go 블로그 시스템입니다.
이 템플릿은 설정을 위해 .env 파일을 사용합니다. 다음 네 가지 값을 복사해 넣으면 바로 시작할 수 있습니다:
GCP_PROJECT_ID=your-gcp-project-id
GCP_REGION=us-central1
GCP_IMAGE_NAME=helloworld
GCP_CLOUDRUN_NAME=helloworld
무엇이든 실행하기 전에, 인증하고 프로젝트를 설정하세요:
gcloud auth login
gcloud config set project YOUR_PROJECT_ID
여러분의 GCP 계정에는 몇 가지 IAM 역할이 필요합니다: 빌드를 제출하기 위한 cloudbuild.builds.editor, 이미지를 Container Registry에 푸시하기 위한 storage.admin, 서비스를 배포하고 관리하기 위한 run.admin, 그리고 배포 중 Cloud Build가 Cloud Run 서비스 계정으로 동작할 수 있도록 하는 iam.serviceAccountUser입니다. 배포가 권한 오류로 실패한다면, 보통 가장 먼저 확인해야 할 곳이 여기입니다.
그다음부터의 워크플로는 단일 명령입니다:
make
이 명령은 내부적으로 gcp-push를 실행하며, 소스를 Cloud Build에 제출하고, Docker 이미지를 빌드하고, 이를 Google Container Registry에 푸시한 뒤, 결과를 공개적으로 접근 가능한 서비스로 Cloud Run에 배포합니다. 완료되면 Cloud Run이 서비스 URL을 출력합니다.
이 템플릿은 Docker 이미지를 로컬 머신이 아니라 Cloud Build를 통해 원격으로 빌드합니다. 원한다면 로컬에서 빌드하고 이미지를 직접 푸시할 수도 있지만, 원격 방식에는 몇 가지 실용적인 장점이 있습니다. 예를 들어 이미 Docker 컨테이너 내부(개발 컨테이너나 CI 환경 등)에서 실행 중이라면, 중첩된 Docker 데몬의 복잡성을 피할 수 있습니다. 연결 속도가 느린 환경에서는 빌드가 전부 GCP 안에서 이루어지므로, 베이스 이미지를 다운로드하고 최종 결과물을 다시 업로드할 필요가 없습니다. 그리고 빌드 규모가 크다면, 로컬 CPU, 메모리, 디스크를 전혀 고려하지 않아도 됩니다.
알아둘 만한 점이 하나 있습니다: Cloud Run은 PORT 환경 변수를 자동으로 주입합니다. 여러분의 Go 앱은 시작 시 이 값을 읽어야 합니다:
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
포트를 하드코딩하면 서비스가 시작되지 않습니다.
이 템플릿은 초기 배포를 처리하지만, 전체 재배포 없이도 시간이 지나면서 환경 변수를 업데이트해야 할 가능성이 큽니다. gcloud CLI에는 이를 위한 플래그가 있습니다:
gcloud run services update SERVICE_NAME \
--update-env-vars KEY1=VALUE1,KEY2=VALUE2
이 플래그에 대한 전체 참조는 Google Cloud Run documentation에서 확인할 수 있습니다.
Cloud Run은 기본적으로 SSL이 이미 처리된 무료 *.run.app URL을 제공합니다. 커스텀 도메인을 원한다면 Cloud Run 콘솔이나 gcloud를 통해 연결할 수 있습니다:
gcloud run domain-mappings create \
--service SERVICE_NAME \
--domain your-domain.com \
--region REGION
그다음에는 제공된 주소를 가리키도록 여러분의 도메인에 CNAME 또는 A 레코드를 추가하면 됩니다. DNS 변경 사항이 전파되면 GCP가 SSL 인증서를 자동으로 발급하고 갱신합니다. 인증서 발급은 DNS TTL에 따라 몇 분에서 몇 시간까지 걸릴 수 있습니다. 한 번 완료되면 모든 것이 관리되므로 다시 손댈 일이 없습니다.
첫 배포에서는 Cloud Build가 의존성을 가져오고, 컴파일하고, 이미지를 푸시합니다. 단순한 앱이라면 대략 2분에서 5분 정도를 예상하면 됩니다. 이후 배포는 레이어가 캐시되기 때문에 더 빠르며, 작은 변경의 경우 보통 2분 이내에 끝납니다. 빠르게 반복 작업하는 상황이라면 이 정도의 대기 시간은 흐름을 유지하기에 충분히 빠릅니다.
로컬 개발에서는 make run이 Docker 없이 서버를 직접 시작합니다. 작업 중 핫 리로드가 필요하다면 air가 이 설정과 잘 어울립니다.
서비스 사용이 끝나면 make gcp-remove로 Cloud Run에서 삭제할 수 있습니다. 이 명령은 Container Registry의 이미지를 정리하지는 않으므로, 스토리지 비용이 걱정된다면 별도로 정리하고 싶을 수 있습니다. 다만 대부분의 프로젝트에서는 그 비용이 무시해도 될 정도로 작습니다.