はじめに
GitHub
の便利な機能の一つに、指定したリポジトリにファイルをコミット、プッシュしたことを契機に、指定のディレクトリ配下のファイルをいい感じのWebページとして公開できるGitHub Pages
という機能があります。
ただ単純にHTML
ファイルを公開するだけではなく、Markdown
形式のファイルであればHTML
形式に変換して公開してくれるため、Markdown
形式で書いたちょっとしたメモを公開したりするのに便利な機能です。
GitHub Pages
はGitHub
の機能となるので、GitHub
以外では使用できませんが、今回はAWS
のサービスだけ使用して、GitHub Pages
のように外部にWebページを公開する機能を実装してみたいと思います。
作成するAWS構成
仕組みとしては以前記事に書いた「AWSの各種パラメータを取得するツールを作りました。」の「AWSのサービスのみ使用したドキュメント生成ツール」で作った機能の流用となります。
利用サービス | 用途 |
---|---|
CodeCommit | HTMLに変換したいMarkdownファイルのコミット用 |
EventBridge | CodeCommitへのプルリクエストやマージを検知するために使用 |
CodeBuild | CodeCommitに格納されたMarkdownファイルをHTMLに変換し、S3に格納する |
S3 | HTMLに変換したファイルを格納して静的Webサイトホスティングで公開する |
AWSリソースの作成
以下より、必要なリソースを作成していきます。
CodeCommitの作成
CodeCommitダッシュボードより「リポジトリ」→「リポジトリを作成」からリポジトリを作成していきます。
あまり設定項目もないので、名前だけ指定して作成します。
項目 | 設定 | 備考 |
---|---|---|
リポジトリ名 | codecommit_pages | 任意の名前を指定 |
説明 | ※空欄 | 今回は未指定 |
タグ | ※指定なし | 今回は未指定 |
追加設定 | ※デフォルトのまま | |
Amazon CodeGuru Reviewer for Java and Pythonを有効にする | チェックなし |
後ほど作成したリポジトリのARNを使用するため、作成したリポジトリを指定して「設定」から「リポジトリARN」を控えておきます。
S3バケットの作成
上記構成図の順番とは異なりますが、先にS3バケットから作成していきます。
作成するS3バケットは生成されたHTMLファイルの格納以外に、格納されたファイルを公開するため、静的Webサイトホスティングも有効化します。
S3基本設定
S3ダッシュボードから「バケット」→「バケットを作成」を選択して以下のようにS3バケットを作成していきます。
今回のS3バケットは静的Webサイトホスティングで公開する必要があるため、ブロックパブリックアクセスの設定のみ、公開用の設定に変更しておきます。
項目 | 設定 | 備考 |
---|---|---|
バケットタイプ | 汎用 | |
バケット名 | codecommit-pages-bucket | 任意の名前を指定 |
オブジェクト所有者 | ACL無効(推奨) | |
このバケットのブロックパブリックアクセス設定 | ※すべてチェックなし | 静的Webサイトホスティングで公開するためチェックをすべて外す |
現在の設定により、このバケットとバケット内のオブジェクトが公開される可能性があることを承認します。 | 有効化 | ブロックパブリックアクセスを無効化する場合に選択が必要 |
バケットのバージョニング | 無効にする | ソースはCodeCommitで管理しているので今回は無効にする |
タグ | ※指定なし | 今回は未指定 |
暗号化タイプ | Amazon S3マネージドキーを使用したサーバー側の暗号化(SSE-S3) | |
バケットキー | 有効にする | |
オブジェクトロック | 無効にする |
バケットポリシー設定
静的Webサイトホスティングを有効化する場合、ブロックパブリックアクセスを無効化してS3バケットを公開できる状態にする必要があるため、誰でもアクセスできる状態となります。
誰でもアクセスできる状態になるのはパブリックリポジトリでGitHub Pages
を有効化した場合でも同様ですが、公開する内容によってはやはりアクセスを制限したい場合もあるかと思いますので、特定のIPアドレスのみ許可するバケットポリシー設定を以下に例として記載しておきます。
設定を行う場合、作成したS3バケットの「アクセス許可」タブの「バケットポリシー」の「編集」から以下のResource
を作成したS3バケットのARN、aws:SourceIp
をアドレス許可したいIPアドレスを指定して「変更の保存」で設定します。
※以下に記載しているIPアドレスは実在しないドキュメント用のIPアドレスなので、環境に合わせて変更してください。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::codecommit-pages-bucket/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"203.0.113.1/32"
]
}
}
}
]
}
特にアクセス制御しなくても良い場合でも、バケットポリシーは必要となるため、その場合はCondition
部分を削除し、以下のように設定してください。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::codecommit-pages-bucket/*"
}
]
}
静的Webサイトホスティング設定
静的Webサイトホスティングを有効化するため、「プロパティ」タブの「静的ウェブサイトホスティング」の「編集」から以下のように設定します。
項目 | 設定 | 備考 |
---|---|---|
静的ウェブサイトホスティング | 有効にする | |
ホスティングタイプ | 静的ウェブサイトをホストする | |
インデックスドキュメント | index.html | |
エラードキュメント | ※空欄 | 今回は特にerrorファイルは使わないため未指定 |
リダイレクトルール | ※空欄 | リダイレクトしないため未設定 |
CodeBuildの作成
今回の機能のメインとなるCodeBuild
を作成していきます。
CodeBuild用IAMポリシーの作成
CodeBuild
でIAMロールを指定する必要があるため、IAMロールを作成するためのIAMポリシーを作成しておきます。
IAMダッシュボードから「ポリシー」の「ポリシーの作成」から以下のように設定していきます。
今回は説明簡略化のため、Resource
指定しない設定としていますが、実際の環境に導入する際には要調整してください。
項目 | 設定 | 備考 |
---|---|---|
ポリシーエディタ | JSON | 今回は以下JSONを指定 |
ポリシー名 | codecommit-pages-codebuild-policy | 任意の名前を指定 |
説明 | ※空欄 | 今回は未指定 |
タグ | ※指定なし | 今回は未指定 |
{
"Statement": [
{
"Action": [
"logs:PutLogEvents",
"logs:CreateLogStream",
"logs:CreateLogGroup"
],
"Effect": "Allow",
"Resource": ["*"]
},
{
"Action": [
"codebuild:UpdateReport",
"codebuild:CreateReportGroup",
"codebuild:CreateReport",
"codebuild:BatchPutTestCases",
"codebuild:BatchPutCodeCoverages"
],
"Effect": "Allow",
"Resource": ["*"]
},
{
"Action": [
"s3:PutObject",
"s3:ListBucket",
"s3:GetObjectVersion",
"s3:GetObject",
"s3:GetBucketLocation",
"s3:GetBucketAcl",
"s3:DeleteObject"
],
"Effect": "Allow",
"Resource": ["*"]
},
{
"Action": "codecommit:GitPull",
"Effect": "Allow",
"Resource": ["*"]
}
],
"Version": "2012-10-17"
}
CodeBuild用IAMロールの作成
IAMロールを作成します。
IAMダッシュボードから「ロール」の「ロールを作成」から以下のように設定していきます。
項目 | 設定 | 備考 |
---|---|---|
信頼されたエンティティタイプ | AWSのサービス | |
サービスまたはユースケース | CodeBuild | プルダウンメニューから選択 |
ユースケース | CodeBuild | |
許可ポリシー | codecommit-pages-codebuild-policy | 先ほど作成したIAMポリシーを指定 |
ロール名 | codecommit-pages-codebuild-role | 任意の名前を指定 |
説明 | ※空欄 | 今回は未指定 |
ビルドプロジェクト作成
ビルドプロジェクトを以下のように設定していきます。
HTMLの生成にはGitHub Pages
でも使用しているJekyll
を使用するため、AWSのマネージド型イメージを使用するのではなくJekyll
のDockerイメージを使用するようにします。
項目 | 設定 | 備考 |
---|---|---|
プロジェクト名 | codecommit-pages-build-proj | 任意の名前を指定 |
追加設定(プロジェクトの設定) | ※デフォルトのまま | 今回はデフォルトのまま未設定 |
ソースプロバイダ | AWS CodeCommit | |
リポジトリ | codecommit_pages | 先ほど作成したリポジトリを選択 |
リファレンスタイプ | ブランチ | |
ブランチ | ※空欄 | ブランチの指定ができないためデフォルトのまま空欄とする |
追加設定(ソース) | ※デフォルトのまま | 今回はデフォルトのまま未設定 |
プロビジョニングモデル | オンデマンド | |
環境イメージ | カスタムイメージ | 今回はjekyllイメージを使用したいためカスタムイメージを選択 |
コンピューティング | EC2 | |
環境タイプ | Linux EC2 | |
イメージレジストリ | その他のレジストリ | 今回はjekyllイメージを使用したいためその他のレジストリを選択 |
外部レジストリのURL | jekyll/jekyll:latest | jekyllイメージのURLを指定 |
レジストリの認証情報 | ※空欄 | パブリックレジストリのため認証なし |
サービスロール | codecommit-pages-codebuild-role | 先ほど作成したIAMロールを指定 |
AWS CodeBuild にこのサービスロールの編集を許可し、このビルドプロジェクトでの使用を可能にする | 有効にする | |
追加設定(環境) | 環境変数のみ設定(次表で記載) | 環境変数以外はデフォルトのままにする |
環境変数 | ※次表参照 | buildspec.ymlで使用する環境変数を指定 |
ビルド仕様 | ビルドコマンドの挿入 | 今回は「エディタに切り替え」から直接以下のbuildspec.ymlの内容をコピペ |
バッチ設定を定義 | 無効にする | ※デフォルトのまま |
アーティファクト1 タイプ | アーティファクトなし | |
追加設定(アーティファクト) | ※デフォルトのまま | 今回はデフォルトのまま未設定 |
CloudWatch Logs | 無効にする | 今回は説明簡略化のため無効 |
S3ログ | 無効にする | 今回はデフォルトのまま未設定 |
buildspec.yml
で使用する環境変数は以下のように指定します。
名前 | 値 | タイプ | 備考 |
---|---|---|---|
REGION | ap-northeast-1 | プレーンテキスト | S3バケットのリージョンを指定 |
REPOSITORY | codecommit_pages | プレーンテキスト | 先ほど作成したリポジトリ名を指定 |
GLIBC_VERSION | 2.35-r1 | プレーンテキスト | AWS CLIインストールに必要のため指定 |
SRC_DIR | ※空欄 | プレーンテキスト | ルートディレクトリ以外に生成用ファイルを格納する場合に指定 |
PROTOCOL | http | プレーンテキスト | 静的Webサイトホスティングはhttpアクセスとなるため、httpを指定 |
S3_BUCKET_NAME | codecommit-pages-bucket | プレーンテキスト | 先ほど作成したS3バケット名を指定 |
SRC_DIR
は生成元のファイルがルートディレクトリではなく別のディレクトリ(例えば/docs
)に存在する場合に指定してください。
SRC_DIR
を指定することで、GitHub Pages
で以下のような特定のブランチ、特定のディレクトリを指定した場合と同等の処理が行われます。
buildspec.yml
の設定は以下をコピペしてください。
version: 0.2
env:
git-credential-helper: yes
phases:
install:
on-failure: ABORT
commands:
# jqとAWS CLI v2のインストール
- apk --update add jq binutils
- wget -O /etc/apk/keyssgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub
- wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk
- wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-bin-${GLIBC_VERSION}.apk
- wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-i18n-${GLIBC_VERSION}.apk
- |
apk add --no-cache --force-overwrite --allow-untrusted \
glibc-${GLIBC_VERSION}.apk \
glibc-bin-${GLIBC_VERSION}.apk \
glibc-i18n-${GLIBC_VERSION}.apk
- /usr/glibc-compat/bin/localedef -i en_US -f UTF-8 en_US.UTF-8
- ln -sf /usr/glibc-compat/lib/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
- wget -O awscliv2.zip https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip
- unzip awscliv2.zip 2>&1 > /dev/null
- aws/install
# 不要なファイルの削除
- rm -rf aws awscliv2.zip glibc-*.apk
build:
on-failure: ABORT
commands:
# JekyllインストールとJekyllに必要なファイルの作成
# Gemfileの作成
- cd /srv/jekyll
- |
cat << _EOF_ > Gemfile
source "https://rubygems.org"
gem 'github-pages', group: :jekyll_plugins
_EOF_
# _config.ymlの作成
- |
cat << _EOF_ > _config.yml
title: ${REPOSITORY}
url: ${PROTOCOL}://${S3_BUCKET_NAME}.s3-website-${REGION}.amazonaws.com
baseurl: /
theme: jekyll-theme-primer
_EOF_
# Bundleのインストール
- chown jekyll:jekyll Gemfile _config.yml
- bundle add webrick
# jekyll-theme-primer用default.htmlの作成
# jekyll-theme-primerのデフォルトレイアウトの場合、GitHubのリポジトリ名を指定しないとエラーとなるためカスタムレイアウトを作成
- mkdir -p ${CODEBUILD_SRC_DIR}/${SRC_DIR}/_layouts
- |
cat << _EOF_ > ${CODEBUILD_SRC_DIR}/${SRC_DIR}/_layouts/default.html
<!DOCTYPE html>
<html lang="{{ site.lang | default: "en-US" }}">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
{% include head-custom.html %}
</head>
<body>
<div class="container-lg px-3 my-5 markdown-body">
{% if site.title and site.title != page.title %}
<h1><a href="{{ "/" | absolute_url }}">{{ site.title }}</a></h1>
{% endif %}
{{ content }}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/4.1.0/anchor.min.js" integrity="sha256-lZaRhKri35AyJSypXXs4o6OPFTbTmUoltBbDCbdzegg=" crossorigin="anonymous"></script>
<script>anchors.add();</script>
</body>
</html>
_EOF_
- chown -R jekyll:jekyll ${CODEBUILD_SRC_DIR}/${SRC_DIR}/_layouts
post_build:
on-failure: ABORT
commands:
# ドキュメント表示用HTMLファイルの作成とS3へのアップロード
# ドキュメントのビルド
- |
bundle exec jekyll build \
--config /srv/jekyll/_config.yml \
--source ${CODEBUILD_SRC_DIR}/${SRC_DIR} \
--destination /srv/jekyll/_site
# S3へのアップロード
- aws s3 sync /srv/jekyll/_site s3://${S3_BUCKET_NAME}/ --exclude "*.md" --delete
buildspec.ymlについて
上記で記載したbuildspec.yml
についてざっくりと以下に示します。
installフェーズ
今回、AWSのマネージド型イメージではなくJekyll
イメージを使用するため、Jekyll
イメージでもAWS CLIを使用できるようにするため、必要なパッケージ等をインストールして、AWS CLIを導入しています。
Jekyll
イメージはAlpine
をベースにしていますが、AWS CLIインストール時に必要となるGLIBC
が標準パッケージにないため、他リポジトリから持ってきたりしています。
buildフェーズ
GitHub Pages
と同じように表示できるようにするため、Jekyll
の設定を色々と行っています。
GitHub Pages
で使われているjekyll-theme-primer
というテーマをそのまま使おうとすると、GitHub
リポジトリ名を指定しないとエラーとなることから、カスタムレイアウトを_layouts/default.html
に作成して、AWSで使用した場合でもエラーが出ないようにしています。
build
フェーズはJekyll
の設定となるため、もし色々とカスタマイズしたい方はJekyll
のドキュメントをよく読んで、build
フェーズで色々と設定してみてください。
post_buildフェーズ
build
フェーズで設定したJekyll
の設定に従って、HTMLファイルを生成しています。
生成したドキュメントは指定したS3バケットに格納されます。
EventBridgeの作成
CodeCommit
へのコミットを契機に先ほど作成したCodeBuild
を実行するためのEventBridge
を作成します。
項目 | 設定 | 備考 |
---|---|---|
名前 | codecommit-pages-eb-rule | 任意の名前を指定 |
説明 | ※空欄 | 今回は未指定 |
イベントバス | default | |
選択したイベントバスでルールを有効にする | 有効 | |
ルールタイプ | イベントパターンを持つルール | |
イベントソース | AWSイベントまたはEventBridgeパートナーイベント | |
メソッド | カスタムパターン(JSONエディタ) | 直接以下のイベントパターンを指定するためカスタムパターンを指定 |
イベントパターン | ※以下イベントパターンのJSON参照 | 以下イベントパターンを指定 |
ターゲットタイプ | AWSのサービス | |
ターゲットを指定 | CodeBuildプロジェクト | |
プロジェクトARN | 先ほど作成したCodeBuildのARNを指定 | |
実行ロール | この特定のリソースについて新しいロールを作成 | 新規作成でも必要な権限が付与されるため今回はデフォルトロールで作成 |
追加設定(ターゲット1) | ※デフォルトのまま | 今回はデフォルトのまま未設定 |
タグ | ※指定なし | 今回は未指定 |
イベントパターンは先程控えたCodeCommit
のARNを指定しつつ以下のように設定。
{
"detail": {
"event": ["referenceCreated", "referenceUpdated"],
"referenceName": ["master"]
},
"resources": ["[先ほど控えたCodeCommitのARNを指定]"],
"source": ["aws.codecommit"]
}
動作確認
ここまでの作業で、GitHub Pages
のように、リポジトリにコミットしたらMarkdownのファイルから公開用HTMLファイルを生成して外部から閲覧できる準備ができたので、実際に動作するかを試してみます。
CodeCommitリポジトリのクローン
先ほど作成したCodeCommit
画面にリポジトリのクローン作成URLが表示されているため、コマンドをコピーして自分の端末にクローンします。
git clone https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/[先ほど作成したCodeCommitリポジトリ名]
リポジトリにテスト用index.mdファイルのプッシュ
きちんとHTMLファイルが生成されるかを確認するため、適当なMarkdownファイルをリポジトリにプッシュしてみようと思います。
先ほどローカルにクローンしたリポジトリに移動し、以下のようなindex.md
ファイルをルートディレクトリに作成して、Markdownファイルをプッシュしてみます。
# CodeCommit Pagesテスト
CodeCommitでGitHub Pagesのような機能を実装するテスト。
## Hello World
- 表テスト
|項目1|項目2|
|:--|:--|
|test1|test2|
- コードブロックテスト
```bash
aws s3 ls
```
git add . && git commit -m "CodeCommit Pagesテスト" && git push -u origin master
公開HTMLファイルの確認
今まで設定した内容に間違いがなければ、リポジトリプッシュを契機にCodeBuild
が動き出し、暫く経つとステータスが「成功」となるはずです。
S3バケットにはindex.md
から生成されたindex.html
とCSSファイルが格納されているassets
が存在しているかと思います。
生成されたHTMLファイルの内容を確認するには、「プロパティ」タブの「静的ウェブサイトホスティング」欄に記載されている「バケットウェブサイトエンドポイント」のリンクをクリックしWebアクセスを行います。
すると以下のようにGitHub Pages
で生成した画面と同等のページが確認できるかと思います。
なお、生成に使用しているジェネレータはGitHub Pages
で使用されているジェネレータと同じく「Jekyll」を使用しているため、ほぼ同等の表示となります。
ちなみに先ほどと同じindex.md
ファイルをGitHub Pages
が有効なGitHub
リポジトリにプッシュしてHTMLファイルを生成したときの例が以下となります。
リポジトリ名をgithub_pages
というリポジトリにしたため、頭のリンク名だけは異なりますが、それ以外に違いがないことが確認できるかと思います。
おわりに
以前「AWSの各種パラメータを取得するツールを作りました。」でGitHub
を用いない場合でも使えるようにした際の副産物として、今回AWSサービスのみでGitHub Pages
のような機能を実装してみました。
ドキュメント生成部分をCodeBuild
で実装している関係上、どうしてもbuildspec.yml
の手入れは必要となってしまいますが、GitHub
を使えない環境でも似た機能を実装したい場合には使えるのではないかと思います。
今回はGitHub Pages
の表示になるべく似せるため、ページのトップにリポジトリ名を表示させたり、GitHub Pages
で使用しているテーマを使っていますが、buildspec.yml
に記載しているJekyll
の設定次第で表記を変えることもできますし、応用してJekyll
以外の静的サイトジェネレータを使ってみても面白いかと思います。
また、今回のリソースとほぼ同じもの(IAMポリシー等は一部リソース指定等行うように修正)を作成できるようにしたterraform
を以下に置いたので、すぐに試してみたい方はこちらを使ってみてください。
- codecommit-pages(terraform格納GitHubリポジトリ)