GCP Cloud Run: Dockerfile이 없는 컨테이너

컨테이너를 사용하면 원하는 곳 어디에서나 코드를 실행할 수 있으며 Docker는 컨테이너를 구축하는 데 널리 사용되는 옵션입니다. 그러나 때로는 Dockerfile을 좋아하고 때로는 (또는 그 이상) Dockerfile을 싫어합니다.

"44% of the containers in the wild had know vulnerabilities for which patches existed. This just shows you that writing your own Dockerfile can actually be quite fraught with errors unless you're an expert or maybe you have a platform team that provides Dockerfiles for you." Src: Buildpacks in Google Cloud



Dockerfile을 작성하는 것은 이미지 크기, 보안, 다단계, 버전 등을 고려할 때 복잡할 수 있습니다. 그렇게 하는 방법은 너무 많습니다!

물론 완벽한 이미지를 얻기 위해 모든 작업을 처리할 수 있지만 컨테이너를 사용하는 경우 조만간 Kubernetes 클러스터(예: GCP의 Cloud Run 또는 GKE) 및 Kubernetes has deprecated Docker에 컨테이너를 배포해야 합니다.

우리는 개발자이므로 코드에 집중해야 합니다...

그래서... 문제를 해결해 줄 빌드팩이 왔습니다!

오늘 우리의 주요 목표는 Buildpacks를 사용하여 Dockerfile 없이 Cloud Run에 간단한 API를 배포하는 것입니다.



코드



Go를 사용하여 간단한 API를 배포할 것입니다.

package main

import (
    "encoding/json"
    "log"
    "net/http"
)

// Response definition for response API
type Response struct {
    Message string `json:"message"`
}

func handler(w http.ResponseWriter, r *http.Request) {

    response := Response{}
    response.Message = "Hello world!"
    responseJSON, err := json.Marshal(response)

    if err != nil {
        log.Fatalf("Failed to parse json: %v", err)
    }

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write(responseJSON)
}

func main() {
    log.Print("starting server...")
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}


Dockerfile 사용



'인기 있는' 방법부터 시작하겠습니다. 즉, Dockerfile을 사용하는 것입니다.

# Source: https://github.com/GoogleCloudPlatform/golang-samples/blob/master/run/helloworld/Dockerfile

FROM golang:1.16-buster as builder

# Create and change to the app directory.
WORKDIR /app

# Retrieve application dependencies.
# This allows the container build to reuse cached dependencies.
# Expecting to copy go.mod and if present go.sum.
COPY go.* ./
RUN go mod download

# Copy local code to the container image.
COPY . ./

# Build the binary.
RUN go build -mod=readonly -v -o server

# Use the official Debian slim image for a lean production container.
# https://hub.docker.com/_/debian
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM debian:buster-slim
RUN set -x && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
    ca-certificates && \
    rm -rf /var/lib/apt/lists/*

# Copy the binary to the production image from the builder stage.
COPY --from=builder /app/server /app/server

# Run the web service on container startup.
CMD ["/app/server"]


.dockerignore를 잊지 마세요!

# The .dockerignore file excludes files from the container build process.
#
# https://docs.docker.com/engine/reference/builder/#dockerignore-file

# Exclude locally vendored dependencies.
vendor/

# Exclude "build-time" ignore files.
.dockerignore
.gcloudignore

# Exclude git history and configuration.
.gitignore
.git


틀림없이 누군가는 이렇게 말할 것입니다.

-"이봐! Dockerfile이 불완전합니다! 다단계를 사용하면 이미지가 더 작아질 것입니다."

그리고... 네, 맞습니다! 이 Dockerfile을 사용하면 이미지가 82.6MB이고 오래 전에 어딘가에서 Go용 다단계 Dockerfile을 발견했습니다. 기록용으로만 here이고 이미지 크기는 13.7MB로 줄었습니다.

좋아요? 전혀 그렇지 않습니다. 먼저 다단계 Dockerfile을 어디서 찾았는지 기억이 나지 않거나 게시물이 오늘 존재하더라도 두 번째로 업데이트(보안 패치)가 필요한 경우 유지 관리자가 프로세스를 이해하기 어려울 수 있습니다.

빌드팩 사용



Buildpacks는 모범 사례에 따라 소스 코드에서 Dockerfile 없이 안전한 프로덕션 준비 컨테이너 이미지를 빠르고 쉽게 생성할 수 있는 오픈 소스 기술입니다. 원본: Announcing Google Cloud buildpacks—container images made easy

빌드팩을 사용하기 위해 가장 먼저 해야 할 일은 Dockerfile과 .dockerignore를 제거하는 것입니다.

그게 다야! 당신은 중요한 것, 즉 당신의 코드를 유지합니다.

빌드팩을 설치하려면 다음으로 이동하십시오. https://buildpacks.io/docs/tools/pack/

이미지를 빌드하려면 다음을 사용하십시오.

pack build my-go-api:v0.1 --builder  gcr.io/buildpacks/builder


이미지를 테스트하려면 다음을 사용하십시오.

docker run --rm -p 8080:8080 my-go-api:v0.1

# In another terminal
curl --request GET --url http://localhost:8080/

# Response expected
# {"message": "Hello world!"}


대박! 이미지가 로컬에서 실행 중이므로 이제 Cloud Run에 배포하겠습니다.

# You can push the image that you built
# but I want to show you that buildpacks can be
# used with gcloud too.

export PROJECT_ID=$(gcloud config list --format 'value(core.project)')

gcloud builds submit --pack image=gcr.io/$PROJECT_ID/my-go-api:v0.1

# Deploy to Cloud Run
gcloud run deploy my-go-api-service \
  --image gcr.io/$PROJECT_ID/my-go-api:v0.1 \
  --region southamerica-east1 \
  --platform managed

curl https://my-go-api-service-[your-hash]-rj.a.run.app
# {"message": "Hello world!"}


다음은 이 게시물의 모든 코드가 포함된 repo입니다. 분기를 확인하세요.

이 게시물이 도움이 되길 바랍니다!

좋은 웹페이지 즐겨찾기