git-remote-s3を使って、AWS内に閉じた自動デプロイ構成を作ってみた
この記事は「BEMALab アドベントカレンダー 2024」13日目の記事です。
はじめに
こんにちは、メンバーズルーツカンパニーの岸本です。
2024年7月25日、AWS CodeCommitの新規受付が終了しました。
慎重に検討を重ねた結果、 2024 年 7 月 25 日をもちまして、 AWS CodeCommit について、新規のお客様向けのアクセスを閉じることを決定いたしました。 AWS CodeCommit を既にお使いのお客様は、これまで通りサービスをご利用いただくことが可能です。 AWS は AWS CodeCommit のセキュリティ、可用性、パフォーマンスの改善に引き続き投資を行ってまいりますが、新機能の導入は予定しておりません。
引用:AWS CodeCommit リポジトリを他の Git プロバイダーに移行する方法
以前から使っていた場合は引き続き使用することができますが、新たにCodeCommitを使用することはできなくなり、CodeCommit + AmplifyのようなAWS内に閉じた構成を簡単に作ることができなくなりました。
GitHubやGitLabであれば引き続きAmplifyとの連携も簡単なので、そちらに移行すれば問題ないのですが、AWS内に閉じたいという需要はまだあるかと思います。
AWS内に構成を閉じるという条件で考えた時にCodeCommitの代替案としてはCodeCatalystが有力かなと考えていたのですが、たまたまgit-remote-s3というものを見つけました。
S3をGitのリモートリポジトリとして扱えるようにするツールのようで、面白そうなので少し試してみることにしました。
git-remote-s3とは
This library enables to use Amazon S3 as a git remote and LFS server.
It provides an implementation of a git remote helper to use S3 as a serverless Git server.
It also provide an implementation of the git-lfs custom transfer to enable pushing LFS managed files to the same S3 bucket used as remote.
引用:awslabs/git-remote-s3
要約すると、S3をGitサーバーとして扱うためのGit Remote Helperとして動いてくれるツールのようです。
Git Remote Helperというのは、Gitがネイティブで対応してないリモートリポジトリとやりとりする時に呼び出されるプログラムです。
S3はGitに対応していないため、S3を対象としたリポジトリ(s3://⚪︎⚪︎⚪︎ or s3+zip://⚪︎⚪︎⚪︎)でgitコマンドを実行した際に、git-remote-s3が良い感じにS3を操作してくれるということです。
構成
今回はお試しで自動デプロイを試すということで、簡単な静的サイトホスティング構成で考えました。
- Git Remote Helper:git-remote-s3
- SSGフレームワーク:Astro
- Gitリモートリポジトリ:S3
- CI/CD:CodePipeline
- ホスティング環境:S3 + CloudFront
git-remote-s3を使う
前提
git-remote-s3を使用する前提条件として、以下の準備が必要です。
- IAMユーザーの作成、ロール設定が完了している
- git-remote-s3を使うにあたって必要なロールの最小構成例がREADME.mdに記載されているので参考にしてみてください。
- AWS CLIがインストールされていて、S3にアクセスできる
- Python 3.9以上が使える
また、フロントエンド環境を用意するために、以下の準備が必要です。
- Node.js v18.17.1またはv20.3.0以上が使える(Astroの使用条件)
インストール
pipを使って、git-remote-s3をインストールします。
python3 -m pip install git-remote-s3
インストールが完了すると、ログにパスが通ってないと表示されるので、各々の環境に合わせてパスを通してください。
WARNING: The scripts git-lfs-s3, git-remote-s3, git-remote-s3+zip and git-s3 are installed in '/Users/⚪︎⚪︎⚪︎/Library/Python/3.9/bin' which is not on PATH.
Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.
筆者はbashを使ってるので.bashrcに追記しました。
export PATH="/Users/⚪︎⚪︎⚪︎/Library/Python/3.9/bin:$PATH"
これでインストールは完了です。
動作確認環境の構築
お試し用のフロントエンド環境を構築します。
今回はAstroを使用することにしました。
適当な開発用ディレクトリを作成し、npmコマンドでAstroの雛形を作成します。
npm create astro@latest
質問は全てEnterを押して、Astroのセットアップウィザードを終了します。
今回は特にフロントエンドは触らないため、ビルドしてページが閲覧できるか確認してフロントエンド環境の構築は終わります。
npm install
npm run build
npm run preview
※ npm installは、後ほどnpm ciする際にエラーが出ないように念の為行っています。
ローカル環境でビルドして、ページが閲覧できることを確認できました。
Gitの動作確認
本題のGit操作を行います。
今回使用するGitリモートリポジトリやデプロイフォルダを作成するために、S3にバケットを作成します。
S3作成する際は、後ほどCodePipelineで読み込むため、バケットのバージョニング設定を有効にする必要があります。
作成できたらPCに戻り、ローカルのリポジトリにS3のリモートリポジトリを追加します。
git-remote-s3を使用してS3のリポジトリを追加する場合、リポジトリのURLは「s3://<バケット名>/<リポジトリ名>」で追加します。
「s3://」を「s3+zip://」にすることでプッシュした際にソースコードがzipファイルとしてS3に保存される機能もあります。今回はCodePipelineを使う際に、これにより生成されるzipファイルを監視対象にしたいため、「s3+zip://」でリポジトリを追加します。
※ 今回は簡単な構成のため、CodePipelineのみを利用してzipファイルを監視対象にする構成にしています。CodeBuildを併用することで、zipファイル以外を監視対象にすることもできると考えていますが検証はできていないので、またいつかやってみたいと思います。
git remote add origin s3+zip://git-s3-test/test-repo
後は通常通り、コミットしてプッシュします。
git add .
git commit -m "first commit"
git push origin main
※ VSCodeなどの、GUI上でGitを操作しても問題ないですが、プッシュした際にエラーが出て上手く行かない可能性があります。
コマンドでプッシュしてもエラーが起きる場合は、以下が問題なく設定できているか確認してください。
- git-remote-s3のパスが通っている
- AWS CLIがインストールされていて、使用できる
- aws configureコマンドでIAMユーザーの設定ができている
- IAMユーザーにS3の権限が付与されている
問題なくプッシュできたら、S3にリポジトリ名でフォルダが作成されていることが確認できます。
ソースコードが入ったzipファイルは、「s3://<バケット名>/<リポジトリ名>/refs/heads/main/repo.zip」に格納されています。
このrepo.zipをCodePipelineの監視対象にすることでプッシュを検知できます。
一度ローカルのフォルダを削除してgit cloneも試してみます。
git clone s3+zip://git-s3-test/test-repo
無事クローンすることができました。S3がGitリモートリポジトリとして機能していそうです。
自動デプロイ
CodePipelineの設定
次はS3のリモートリポジトリにプッシュしたら自動でデプロイする処理を作ります。
CodePipelineでビルドしS3へデプロイ、CloudFrontからホスティングします。
ステップ1. Choose creation option
Build custom pipelineを選択します。
ステップ2. パイプラインの設定を選択する
特にデフォルト設定から変更していません。
ステップ3. ソースステージを追加する
ここで先ほど生成されているのを確認したS3のrepo.zipを設定します。
ステップ4. ビルドステージを追加する
ビルドコマンドには、npm ciとnpm run buildを設定します。また、ここでは設定しきれない内容もあるため、後ほどビルド処理は追加で設定を行います。
ステップ5. デプロイステージを追加する
デプロイ先のS3を設定し、「デプロイする前にファイルを抽出する」にチェックを入れます。
これでCodePipeline作成を完了します。
しかし、これでは設定が不十分なので、再度作成したCodePipelineを編集します。
まず、ビルド設定を変更します。
出力アーティファクトに「BuildArtifact」を設定し、FilesにAstroでビルドファイルが保存されるディレクトリ配下「dist/**/*」を指定して、「Add to file paths」を押します。
次にデプロイ設定を変更します。
アクショングループを追加して、デプロイ前にS3の古いデプロイファイルを削除する処理を追加します。
アクション名はアクションプロバイダーは「AWS Commands」にし、コマンドには以下のS3のファイルを削除するコマンドを指定します。
aws s3 rm s3://git-s3-test/app/dist/ --recursive
次にデプロイアクションを修正し、入力アーティファクトをSourceArtifactから、先ほど作成したBuildArtifactを指定し、編集を完了します。
これでPipelineの設定が完了しました。変更をリリースして、ビルドを行います。
無事ビルドが完了すると、S3にappフォルダが作成されており、中にビルドファイルが格納されています。
CloudFrontの設定
最後にCloudFrontでS3のファイルをホスティングするように設定します。
CloudFrontのディストリビューションを作成します。
入力内容は以下の通りです。
- Origin domainにデプロイ先のS3を指定
- Origin pathに「/app/dist」を指定
- オリジンアクセスで「Origin access control settings (recommended)」を選択して「Origin access control」にデプロイ先のS3を設定
必要に応じて、S3のバケットポリシーを編集する必要が出てくるので、変更してください。
CloudFrontのページにアクセスしてみます。
無事アクセスできました。
ローカルで変更してプッシュし、自動デプロイされるか試します。
testディレクトリを作成し、新しいページを作成しました。プッシュします。
S3への変更を検知して、CodePipelineのビルドが走り始めました。
無事ビルドとデプロイが完了したので、test配下のページを確認してみます。
問題なく確認できました。
さいごに
無事git-remote-s3を利用し、CodePipeline + S3 + CloudFrontの自動デプロイ構成を構築できました。CodeCommitを完全に代替できている環境ではありませんが、一応AWS内に閉じた構成にはなっています。
本番利用するかどうかは考慮の予知があると思いますが、お手軽Gitサーバーとしては良いかなと思いました。