透過Gitlab CI將Image發布至GCP

2022/10/18

設定Gitlab Deploy Token帳號

在Gitlab中的Settings > Repository頁面設定Deploy Token

並給予read_registrywrite_registry的權限(scope)

設定好後留存好該deploy token的帳號密碼(密碼一定要留存好因為離開頁面後無法再取得)

 

設定Service Account

 

Container Registry

因為操作Container Registry的實際情況為儲存Image至Cloud Storage

因此這個操作的Service Account必須擁有Cloud Storage的寫入權限

這邊就會給予該Service Account一個Storage Admin的Role

設定好之後就建立Service Account Key留存

 

Artifact Registry

如果是要上傳至Artifact Registry中

Service Account則是要給一個Artifact Registry Admin的Role

 

Gitlab CI/CD環境變數設定

前往Settings > CI/CD頁面

設定Variables

 

GCP_SERVICE_ACCOUNT

設定為File Type

Value為Service Account Key Json內容

 

GITLAB_REGISTRY_WRITER_PASSWORD

值為剛才建立的deploy token密碼

 

.gitlab-ci.yml(Container Registry)

相關情境

  • Container Registry Repository: gcr.io/project-foobar/demo

 

gitlab-ci.yml

image: docker

variables:
  GITLAB_REGISTRY_WRITER_USERNAME: gitlab+deploy-token-123456

# 將image打包至Gitlab Registry
build:
  stage: build
  variables:
    GITLAB_CI_IMAGE_NAME: $CI_REGISTRY_IMAGE/demo
  services:
    - docker:dind
  only:
    variables:
      - $CI_COMMIT_MESSAGE =~ /build-demo/
      - $CI_COMMIT_TAG =~ /build-demo/
  before_script:
    # docker登入gitlab registry host
    - docker login $CI_REGISTRY -u $GITLAB_REGISTRY_WRITER_USERNAME -p $GITLAB_REGISTRY_WRITER_PASSWORD
  script:
    - docker build -t $GITLAB_CI_IMAGE_NAME:$CI_COMMIT_SHORT_SHA -t $GITLAB_CI_IMAGE_NAME:latest .
    - docker push $GITLAB_CI_IMAGE_NAME:$CI_COMMIT_SHORT_SHA
    - docker push $GITLAB_CI_IMAGE_NAME:latest

push-to-gcp:
  stage: build
  variables:
    GITLAB_CI_IMAGE_NAME: $CI_REGISTRY_IMAGE/demo
    GCP_IMAGE: gcr.io/$project-1/demo
  services:
    - docker:dind
  only:
    variables:
      - $CI_COMMIT_MESSAGE =~ /push-to-gcp/
      - $CI_COMMIT_TAG =~ /push-to-gcp/
  before_script:
    - docker login $CI_REGISTRY -u $GITLAB_REGISTRY_WRITER_USERNAME -p $GITLAB_REGISTRY_WRITER_PASSWORD
    # docker透過service account登入GCR host
    - cat $GCP_SERVICE_ACCOUNT | docker login -u _json_key --password-stdin https://gcr.io
  script:
    # 先pull gitlab container registry image
    - docker pull $GITLAB_CI_IMAGE_NAME:latest
    # 打新的tag
    - docker tag $GITLAB_CI_IMAGE_NAME:latest $GCP_IMAGE:latest
    # push至Google Container Registry
    - docker push $GCP_IMAGE:latest

 

.gitlab-ci.yml(Artifact Registry)

相關情境

  • Artifact Registry Repository: asia-east.docker.pkg.dev/project-foobar/demo

 

gitlab-ci.yml

image: docker

variables:
  GITLAB_REGISTRY_WRITER_USERNAME: gitlab+deploy-token-123456

# 將image打包至Gitlab Registry
build:
  stage: build
  variables:
    GITLAB_CI_IMAGE_NAME: $CI_REGISTRY_IMAGE/demo
  services:
    - docker:dind
  only:
    variables:
      - $CI_COMMIT_MESSAGE =~ /build-demo/
      - $CI_COMMIT_TAG =~ /build-demo/
  before_script:
    # docker登入gitlab registry host
    - docker login $CI_REGISTRY -u $GITLAB_REGISTRY_WRITER_USERNAME -p $GITLAB_REGISTRY_WRITER_PASSWORD
  script:
    - docker build -t $GITLAB_CI_IMAGE_NAME:$CI_COMMIT_SHORT_SHA -t $GITLAB_CI_IMAGE_NAME:latest .
    - docker push $GITLAB_CI_IMAGE_NAME:$CI_COMMIT_SHORT_SHA
    - docker push $GITLAB_CI_IMAGE_NAME:latest

push-to-gcp:
  stage: build
  variables:
    GITLAB_CI_IMAGE_NAME: $CI_REGISTRY_IMAGE/demo
    ARTIFACT_REGISTRY_REGION: asia-east1
    GCP_IMAGE: $ARTIFACT_REGISTRY_REGION-docker.pkg.dev/project-foobar/demo
  services:
    - docker:dind
  only:
    variables:
      - $CI_COMMIT_MESSAGE =~ /push-to-gcp/
      - $CI_COMMIT_TAG =~ /push-to-gcp/
  before_script:
    - docker login $CI_REGISTRY -u $GITLAB_REGISTRY_WRITER_USERNAME -p $GITLAB_REGISTRY_WRITER_PASSWORD
    # docker透過service account登入Artifact Registry host
    - cat $GCP_SERVICE_ACCOUNT | docker login -u _json_key --password-stdin https://$ARTIFACT_REGISTRY_REGION-docker.pkg.dev
  script:
    # 先pull gitlab container registry image
    - docker pull $GITLAB_CI_IMAGE_NAME:latest
    # 打新的tag
    - docker tag $GITLAB_CI_IMAGE_NAME:latest $GCP_IMAGE:latest
    # push至Google Container Registry
    - docker push $GCP_IMAGE:latest

 

差異比較

其實比較一下上面的兩種.gitlab-ci.yml

主要就是Artifact Registry的Repository上有region(或location)

所以在push image的時候位置不同

 

另外在docker login的時候也稍微不同

# Container Registry
cat $GCP_SERVICE_ACCOUNT | docker login -u _json_key --password-stdin https://gcr.io

# Artifact Registry
cat $GCP_SERVICE_ACCOUNT | docker login -u _json_key --password-stdin https://$ARTIFACT_REGISTRY_REGION-docker.pkg.dev