Java jib Gradle 使用 GitLab CI/CD 自動上傳 Docker 到 GitLab Container Registry、Azure Container Registry 與 Amazon Elastic Container Registry

最近在公司的案子有一個需求是希望上傳 Java 的 Code 進去 GitLab 之後可以自動上傳 Docker 到雲端儲存庫,目前的需求有 Azure Container Registry 與 Amazon Elastic Container Registry 而在本地有 GitLab Container Registry,而這個專案使用了容器化工具 Jib 與自動化建構工具 Gradle,但是我認真對 Java 不熟所以研究了一陣子,這邊總結一下使用方法

jib Gradle 上傳 GitLab Container Registry

jib 使用 Gradle 本身就有支援自動上傳 Container Registry 我們可以在 jib-gradle-plugin 裡面找到設定方法,基本上上傳的指令很簡單只要使用以下就可以了

gradle jib \
    -Djib.to.image=myregistry/myimage:latest \
    -Djib.to.auth.username=$USERNAME \
    -Djib.to.auth.password=$PASSWORD

所以在 GitLab CI 就可以直接使用以下完成設定,這邊的 CI_REGISTRY_IMAGECI_REGISTRY_USERCI_REGISTRY_PASSWORD 是系統開啟的時候就有的環境變數,所以不用設定就可以直接使用

image: docker:latest
services:
  - docker:dind

variables:
  DOCKER_DRIVER: overlay
  GRADLE_OPTS: "-Dorg.gradle.daemon=false"

before_script:
  - export GRADLE_USER_HOME=`pwd`/.gradle

stages:
 - build
 - deploy

gradle-jib-gitlab:
  image: gradle:alpine
  stage: build
  script:
    - gradle jib -Djib.to.image=${CI_REGISTRY_IMAGE} -Djib.to.auth.username=${CI_REGISTRY_USER} -Djib.to.auth.password=${CI_REGISTRY_PASSWORD}

如果要新增版本可以修改 -Djib.to.image=${CI_REGISTRY_IMAGE} 改成 -Djib.to.image=${CI_REGISTRY_IMAGE}/${CI_COMMIT_TAG} 在後面加上版本號或是修改 build.gradle 在裡面加上版本號

如果想要參考更多 GitLab 預設的參數可以參考 https://docs.gitlab.com/ee/ci/variables/

jib {
    jib.from.image = "openjdk:8-jre-slim"
    jib.to.tags = ['1.0.0']
}

基本上只要使用以上就可以把 GitLab Container Registry 推進去了

jib Gradle 上傳 Azure Container Registry

而我們在使用的 Azure Container Registry 其實也是使用固定帳號密碼,因此修改一下剛剛的 .gitlab-ci.yml 就可讓 Azure Container Registry 也正常上傳了,不過這邊要注意一下我設定了三個環境變數

  • AZURE_REGISTRY_IMAGE
  • AZURE_REGISTRY_USER
  • AZURE_REGISTRY_PASSWORD

要放到 GitLab 裡面的 Settings -> CI/CD -> Variables 就可以了!

image: docker:latest
services:
  - docker:dind

variables:
  DOCKER_DRIVER: overlay
  GRADLE_OPTS: "-Dorg.gradle.daemon=false"

before_script:
  - export GRADLE_USER_HOME=`pwd`/.gradle

stages:
 - build
 - deploy

gradle-jib-gitlab:
  image: gradle:alpine
  stage: build
  script:
    - gradle jib -Djib.to.image=${CI_REGISTRY_IMAGE} -Djib.to.auth.username=${CI_REGISTRY_USER} -Djib.to.auth.password=${CI_REGISTRY_PASSWORD}

gradle-jib-gitlab-azure:
  image: gradle:alpine
  stage: build
  script:
    - gradle jib -Djib.to.image=${AZURE_REGISTRY_IMAGE} -Djib.to.auth.username=${AZURE_REGISTRY_USER} -Djib.to.auth.password=${AZURE_REGISTRY_PASSWORD}

jib Gradle 上傳 Amazon Elastic Container Registry(ECR)

在這邊最麻煩的就是上傳 ECR 因為在 AWS 裡面沒有辦法設定固定密碼,如果要上傳 Docker 到 ECR 一定要使用 aws ecr get-login-password --region us-west-2 先取得登入 Docker 的 token 登入後才可以取得上傳權限,雖然我們可以在 jib-gradleplugin 看到我們可以使用 credential helpers 而且它支援了 docker-credential-ecr-login,而我們前面使用的 docker image gradle:alpine 並沒有辦法安裝任何的套件,所以沒有辦法安裝 docker-credential-ecr-loginAWS CLI,我弄了很久都沒有辦法成功上傳 Docker 到 ECR 上面,因此我自己寫了一個 Docker image 來解決這件事情,如果有需要的朋友可以直接使用我的 gradle-aws-cli,我在裡面加入 docker-credential-ecr-loginAWS CLI

有了我準備的 docker image 就可以來修改 .gitlab-ci.yml 這邊我們需要設定的環境變數

  • ECR_REGISTRY_IMAGE
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_DEFAULT_REGION
 image: docker:latest
services:
  - docker:dind

variables:
  DOCKER_DRIVER: overlay
  GRADLE_OPTS: "-Dorg.gradle.daemon=false"

before_script:
  - export GRADLE_USER_HOME=`pwd`/.gradle

stages:
 - build
 - deploy

gradle-jib-gitlab:
  image: gradle:alpine
  stage: build
  script:
    - gradle jib -Djib.to.image=${CI_REGISTRY_IMAGE} -Djib.to.auth.username=${CI_REGISTRY_USER} -Djib.to.auth.password=${CI_REGISTRY_PASSWORD}

gradle-jib-gitlab-azure:
  image: gradle:alpine
  stage: build
  script:
    - gradle jib -Djib.to.image=${AZURE_REGISTRY_IMAGE} -Djib.to.auth.username=${AZURE_REGISTRY_USER} -Djib.to.auth.password=${AZURE_REGISTRY_PASSWORD}

gradle-jib-gitlab--aws:
  image: clarencetw/gradle-aws-cli:6.9.0-jdk8
  stage: build
  script:
    - gradle jib -Djib.to.image=${ECR_REGISTRY_IMAGE} -Djib.to.credHelper="ecr-login"

設定完後就可以自動上傳 Docker 到 ECR 了!

結論

用了以上的腳本就可以自動上傳到 GitLab Container Registry、Azure Container Registry 與 Amazon Elastic Container Registry