💭

AWS CodeBuildでSpring Bootアプリケーションのビルド

2022/10/16に公開

AWS CodeBuildでSpring Bootアプリケーションのビルド

ここからが本題でGitHubで管理しているSpring BootアプリケーションをAWS上のEC2に自動でデプロイしていきます。

最終的なシステム構成

最終的な構成は以下の通りとなります。
今回はCodeBuild環境を構築します。

今回のシステム構成

Dockerコンテナ上で確認した手順をもとにAWS CodeBuildでGitHub上のSpring Bootアプリのソースコードをビルドする環境を構築します。

今回の構成は以下となります。

CodeBuildで④⑤を実行するように環境を構築していきます。
そのために以下の二つを構築します。

作成物 説明
CodeBuildプロジェクト 入力となるGitHubのリポジトリやビルドの仕様が記述されているファイルなどを指定します。こちらからビルドを実行して、結果の確認も行います。
buildspec.yml ビルドの仕様を記載したYaml形式のファイル。実行するLinuxのコマンドやS3にアップロードするファイルパスなどを記述します。

ソースコード

今回作成したソースコードは以下から参照できます。
buildspec.ymlファイルを新規に追加しているだけです。
https://github.com/ryotsuka7/spring-boot-demo/tree/v1.0.1

CodeBuildによるビルド環境の構築

ここから実際にビルド環境を構築していきます。

ビルドしたjarファイルをアップロードするS3バケットの作成

CodeBuildでビルドして生成されたjarをアップロードするS3バケットを作成します。
設定はデフォルトのままで問題ありません。
ここでは、spring-boot-demo-build-bucketという名称のバケットを作成しています。

CodeBuild用ブランチの作成(任意)

CodeBuild環境を構築するにあたって、GitHub上に何度もソースをPushして実行しては確認、ということを繰り返します。
ちょっとしたデバッグを仕込むためにもPushする必要があります。

masterやdevelopなどソースコードの大元を管理するブランチに何度もCommit/Pushするとコミット履歴が汚れてしまうので、
CodeBuild開発用の一時的なブランチを作成して、一番最後にmasterにPullRequestする際にコミットを一つにまとめます。

以下の通り、IntelliJ IDEAでブランチを作成します。

buildspec.ymlの新規作成

CodeBuildのビルドの仕様を定義するbuildspec.ymlを新規に作成します。
CodeBuildでGitHubからソースを取得して、ルートフォルダに配置する必要があるため、
Javaプロジェクトのルートに新規作成し、GitHubにPushします。
Push先のブランチはここではdev_codebuildとしています。

buildspec.ymlの内容は以下。

version: 0.2

phases:
  pre_build:
    commands:
      - echo start pre build.

      # ログインユーザーの確認
      - id
      # OS情報の確認
      - cat /etc/system-release
      - cat /etc/os-release
      # 各種パッケージの最新化
      - yum update -y
      # タイムゾーンの変更
      - date
      - cp /usr/share/zoneinfo/Japan /etc/localtime
      - date
      # Javaのインストール
      - yum install -y java-17-amazon-corretto
      - java -version
      - /usr/sbin/alternatives --set java /usr/lib/jvm/java-17-amazon-corretto.aarch64/bin/java
      - java -version
      - /usr/sbin/alternatives --display java
      # JAVA_HOME環境変数の設定
      - export JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.aarch64
      # Mavenのインストール
      - wget https://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
      - sed -i s/\$releasever/7/g /etc/yum.repos.d/epel-apache-maven.repo
      - sed -i s/\$basearch/x86_64/g /etc/yum.repos.d/epel-apache-maven.repo
      - yum install -y apache-maven
      - mvn -version

      - echo finish pre build.

  build:
    commands:
      - echo start build.

      # Spring Bootプロジェクトのビルド(jarの作成)
      - mvn package
      - ls -l target

      - echo finish build.

  post_build:
    commands:
      - echo start post build.

      # S3にアップロードするファイルを所定のディレクトリにコピー
      - mkdir artifacts
      - cp target/spring-boot-demo-0.0.1-SNAPSHOT.jar artifacts

      - echo finish post build.

artifacts:
  # S3にアップロードするファイルを指定
  files:
    - spring-boot-demo-0.0.1-SNAPSHOT.jar
  # ベースディレクトリ
  base-directory: artifacts

実行フェーズはpre_build、build、post_buildに分かれています。
全ての処理をbuildに記述しても良いのですが、CodeBuildで実行する際にそれぞれのフェーズに分かれて結果や処理時間を確認することができるので、適切に使い分けた方が保守性は良いです。
ここでは、以下の通り使い分けています。

フェーズ 内容
pre_build Spring Bootプロジェクトのビルドに必要なJavaなど各種コマンドのインストール
build 実際のビルド処理(mvn package
post_build モジュールをS3にアップロードするためのファイルの配置

artifactではS3にアップロードするファイルを指定しています。

CodeBuildプロジェクトの作成

ここからAWSマネジメントコンソールからCodeBuildプロジェクトを作成していきます。
CodeBuildの画面を表示して、ビルドプロジェクトを作成するをクリック。

プロジェクト作成画面が表示されます。
設定内容の要点は以下の通りです。
Zipにする設定を忘れないようにしてください。

  • ソースコードについてはGitHubのURLを入力します。
    ソースバージョンにブランチdev_codebuildを指定しています。
  • CodeBuildはDockerコンテナ上で実行されますが、OSとしてAmazon Linux2を指定しています。
  • アーティファクトでビルドしたモジュールのアップロードについての設定を行います。
    • アップロード先としてAmazon S3を指定
    • バケット名は事前に作成したspring-boot-demo-build-bucketを指定
    • アーティファクトのパッケージ化はZipを指定します。
      このあと、CodeDeployでCodeBuildで生成したモジュールを指定しますが、圧縮ファイルである必要があります。
      CodePipelineではこの辺は自動でやってくれますが、それと同等の仕様で確認するためにここはZipを指定する必要があります。









CodeBuildプロジェクトの実行と結果の確認

ビルドの実行

ビルドプロジェクトが作成されたら下の画面が表示されます。
試しにビルドを開始ボタンをクリックして、実行してみましょう。

実行中はステータスが実行中となります。

エラーなく完了したらステータスが成功となり、開始、終了時刻が表示されます。
7分程度かかっていることが分かります。

ビルド結果の確認

さらに詳細を見るためには画面下部のフェーズ詳細タブをクリックします。
フェーズごとの処理時間も表示され、どこで時間がかかっているか把握できます。
また、エラーとなった場合もどのフェーズでエラーとなったかこちらで分かります。

フェーズごとの処理時間をみると

  • 特にPRE_BUILDとBUILDで時間がかかっている
  • これらはbuildspec.ymlのpre_buildbuildで記述した処理。
  • pre_buildで、何で時間がかかっているか調べるためにログを参照します。
    下図の画面でログ全体の表示をクリックすると、CloudWatch Logsでログ全量が表示されます。
    確認するとyum updateで90秒程度かかっているので、処理時間のほとんどはこちらとなります。
  • buildではmvn packageして実行していないので、ソースをビルドして、jarを生成する処理で時間がかかっています。
    ログを見るとほとんどの時間は依存関係をもとに必要なjarをダウンロードするところで時間がかかっています。

※ 以下の画面でログ全体の表示をクリック

S3バケットをみてみましょう。
spring-boot-demo-build-prjというCodeBuildプロジェクト名と同名のファイルができています。
こちらをダウンロードして、zipファイルを解凍すると、spring-boot-demo-0.0.1-SNAPSHOT.jarが含まれていました。

ブランチのマージ(任意)

CodeBuild開発用に作成したdev_codebuildブランチをmasterブランチにマージします。

GitHubでリポジトリを開くとCompare & pull requestボタンが表示されているので、クリックします。

dev_codebuildからmasterブランチへのマージであることを確認します。
また、差分等が確認できるので、そちらも確認します。
問題なければ、任意のタイトルをつけてCreate pull requestボタンをクリックします。

Pull Requestが作成され、表示されます。

dev_codebuildのコミットを一つのコミットにまとめてからmasterにマージしたいので、Squash and mergeを選択します。
ブランチのコミットを一つにまとめずにそのまま残す場合はMerge pull requestを選択します。

一つにまとめたコミットのメッセージを入力します。
Confirm squash and mergeをクリックすると実際にマージが行われます。

開発用に作成したブランチなので、削除してしまいます。
Delete branchボタンをクリックします。

ローカルリポジトリのdev_codebuildも削除します。
こちらはIntelliJ IDEAで操作します。
masterブランチにCheckoutします。

dev_codebuildブランチを選択して、ブランチ削除ボタンをクリックします。

ブランチを削除したらCodeBuildのソースで指定しているブランチも変更します。
編集->ソースをクリックして、ソース編集画面を開きます。

プロジェクト作成時に指定したソースバージョンmasterに変更します。
試しにビルドを実行してエラーなく完了すること確認します。

Tips: ブレークポイントによるデバッグについて

上記では、さらりと正常に終了する手順を説明しましたが、ここに至るまでに結構思考錯誤しました。
CodeBuildはサーバーレスなため、エラーが発生してもOSにログインして調査が普通ではできません。
ただし、buildspec.ymlにブレークポイントを記載して一部設定を変更してビルドを実行することで、処理を一時的に停止させて、OSにログインして状態を確認することができます。
まずはログを参照して調査しますが、行き詰まったら、ブレークポイントを使った調査をお勧めします。

ブレークポイントの設定手順

デバッグの手順について説明します。

AWSの公式のリファレンスは以下になります。
https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/session-manager.html

処理を一時停止したいと箇所でbuildspec.ymlcodebuild-breakpointを記載します。
公式サイトからの引用となりますが、以下な感じで停止したい箇所にブレークポイントを記述します。

ブレークポイントの例

phases:
  pre_build:
    commands:
      - echo Entered the pre_build phase...
      - echo "Hello World" > /tmp/hello-world
      - codebuild-breakpoint

セッション接続の有効化してのビルド実行手順

buildspec.ymlにブレークポイントを設定した上で、ビルドを実行する際に以下の通りの手順で実行するとブレークポイントの位置で処理が一時停止します。

ビルドを実行する際に上書きでビルドを開始するをクリックします。

ビルドを開始画面にて高度なビルドの上書きボタンをクリックします。
(標準な設定より高度なビルド設定を行います。)

環境セクションのセッション接続の有効化AWS CodeBuildにこのサービスロールの編集を許可し、このビルドプロジェクトでの使用を可能にするの二つのチェックボックスを有効にします。

上記の設定を行ったうえでビルドを開始ボタンをクリックしてビルドを行います。
問題なく設定できている場合は、ブレークポイントの位置で処理が一時停止します。
ログには以下のように出力されます。

[Container] 2022/10/16 02:12:18 Running command codebuild-breakpoint
2022/10/16 02:12:18 Build is paused temporarily and you can use codebuild-resume command in the session to resume this build

ビルドステータスセクションにAWSセッションマネージャーへのリンクが表示されるので、クリックすると別タブで画面が開きます。

新しく開いた画面はLinuxのコンソールが表示され、ここからコマンドを入力することができます。

処理を再開する場合はログにも出力されていましたが、以下の通りコマンドを実行します。

codebuild-resume

以上がCodeBuildでのブレークポイントの使い方ですが、手順もシンプルなので、調査が必要な場合は使ってみることをお勧めします。

記事一覧

第一回 Spring Bootを使ったWebAPIの作成

第二回 IntelliJ IDEAを使って、Spring BootプロジェクトをGitHubにPush

第三回 Dockerコンテナ上でSpring Bootアプリケーションのビルド

第四回 AWS CodeBuildでSpring Bootアプリケーションをビルド

第五回 AWS CodeDeployでSpring Bootアプリケーションのデプロイ

第六回 CodePipelineでSpring BootアプリをCI/CD

Discussion