ortの灰ログ

人狼のことや技術のことや日々雑感

Oracle CloudのVM.Standard.A1.Flexでarm64用のSpring Boot docker imageをbuildする

この記事は

タイトルとっちらかってますね
Always Free枠で借りているVM.Standard.A1.Flexに構築したKubernetes上でSpring Bootプロジェクトを動作させたいので、
同環境に構築したself-hosted runnerでarm64用のdocker imageをbuildしてghcr.ioにpushするところまでやろう、という記事です。

前提

  • VM.Standard.A1.FlexGithub Actionsのself-hosted runnerが設定済み
  • Java8(他でもdocker imageやjdkが見つかればいけるはずです)

参考: Oracle CloudのVM.Standard.A1.FlexにGithub Actionsのself-hosted runnerを設定する - ortの灰ログ

やること

  • Spring Boot
    • jibを使ってarm64用のdocker imageを作成する設定を追加
  • Github Actions
    • developブランチにpushされたらVM.Standard.A1.Flex上でdocker image build
    • ついでにghcr.ioにpush

Spring Boot

jibを使ってdocker imageをbuildしてpushする設定を追加

GitHub - GoogleContainerTools/jib: 🏗 Build container images for your Java applications. を使います。

※ gradle かつKotlinでの例になるので、maven等使っている方は読み替えてください。

やることは単純で、build.gradle.ktsに若干設定を追加するだけです。

build.gradle.kts

plugins {
    java
    id("org.springframework.boot") version "2.3.0.RELEASE"
    id("io.spring.dependency-management") version "1.0.9.RELEASE"
    kotlin("jvm") version "1.3.72"
    kotlin("plugin.spring") version "1.3.72"
    # 追加
    id("com.google.cloud.tools.jib") version "2.6.0"
}

...

# 以下追加
jib {
    from {
        image = "arm64v8/openjdk:8"  # DockerHubで探してarm64用のopenjdkを使う。
        platforms {
            # linux & arm64を指定する
            platform {
                architecture = "arm64"
                os = "linux"
            }
        }
    }
    to {
        image = "ghcr.io/{githubユーザ名}/{docker image名}"
    }
    container {
        # この辺りはお好みで
        jvmFlags = listOf(
            "-server",
            "-Djava.awt.headless=true",
            "-Dspring.profiles.active=production"
        )
        creationTime = "USE_CURRENT_TIMESTAMP"
    }
}

Github Actions

  • developにpushされたら起動
  • 環境を汚さないようにJDKセットアップ(arm64版)
  • buildしてghcr.ioにpush

完成形

.github/workflows/deploy.yml

name: deploy

on:
  push:
    branches:
      - develop

jobs:
  delivery:
    runs-on: [ self-hosted ]
    steps:
      - name: clone repository
        uses: actions/checkout@v2
        with:
          ref: develop

      - name: download arm64 JDK 8
        run: |
          download_url="https://cdn.azul.com/zulu-embedded/bin/zulu8.54.0.21-ca-jdk8.0.292-linux_aarch64.tar.gz"
          wget -O $RUNNER_TEMP/java_package.tar.gz $download_url

      - name: set up JDK 8
        uses: actions/setup-java@v2
        with:
          distribution: 'jdkfile'
          jdkFile: ${{ runner.temp }}/java_package.tar.gz
          java-version: '8'
          architecture: arm64

      - name: build
        run: |
          ./gradlew jibDockerBuild

      - name: deploy
        run: |
          docker login ghcr.io -u {githubユーザー名} -p ${{ secrets.PACKAGE_PAT }}
          docker push ghcr.io/{githubユーザー名}/{jibに設定したdocker image名}

事前準備

write:packages権限がついたPersonal Access Tokenを用意

https://github.com/settings/tokenswrite:packages権限がついたトークンを作成、トークンをメモしておく

Secretsにトークンを設定

Githubの該当リポジトリでSettings -> Secrets -> New repository secretと進んで先ほどのトークンを設定。
ここではPACKAGE_PAT という名前にする。

JDKインストール

ここからはymlの話。
self-hosted runnerが動作するサーバーにJDKをインストールしても良いのだが、
環境を汚したくないので
GitHub - actions/setup-java: Set up your GitHub Actions workflow with a specific version of Java を使用する。

ただし、

      - uses: actions/setup-java@v1
        with:
          java-version: 8

とかにしてもx64用が使われてしまうのでarm64では動作しない。

https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Installing-Java-from-local-file

にあるように、自分で用意したarm64用のjdkを使わせる必要がある。
というわけで、こんな感じにすればできた。

      - name: download arm64 JDK 8
        run: |
          download_url="https://cdn.azul.com/zulu-embedded/bin/zulu8.54.0.21-ca-jdk8.0.292-linux_aarch64.tar.gz"
          wget -O $RUNNER_TEMP/java_package.tar.gz $download_url

      - name: set up JDK 8
        uses: actions/setup-java@v2
        with:
          distribution: 'jdkfile'
          jdkFile: ${{ runner.temp }}/java_package.tar.gz
          java-version: '8'
          architecture: arm64

他のバージョンを使いたい場合は同じようにarm64版のjdkを探してください。確か11は見つかった記憶があります。

jibでbuildしてpush

これは簡単。便利ですね。 ghcr.ioへpushするので先ほど設定したwrite:packages権限がついたpersonal access tokenを使っています。

      - name: build
        run: |
          ./gradlew jibDockerBuild

      - name: deploy
        run: |
          docker login ghcr.io -u {githubユーザー名} -p ${{ secrets.PACKAGE_PAT }}
          docker push ghcr.io/{githubユーザー名}/{jibに設定したdocker image名}