いっしきまさひこBLOG

AI・機械学習関連、Web制作関連、プログラミング関連、旅行記録などなど。一色政彦。

CMSサイト(動的)→S3(静的)移行を自動化! Pythonスクリプト公開中

「CMSで管理されている動的なWebサイトを静的サイトに移行したい」と考えている人向けの記事です。CMSでサイトを頻繁に更新する必要がなくなった場合や、運用コストを削減したい場合などで、静的サイトへの移行は大きなメリットをもたらします。以下では、私が実践した手法と、そのために作成したPythonスクリプトを紹介します。

課題と解決策

CMSを利用した動的サイトには以下の課題があります:

  • サーバーコストが高い
  • CMSのメンテナンスが手間

これらを解決するため、私はCMSサイトを静的化し、Amazon S3+CloudFrontでホスティングする方法を選びました。この作業を効率化するため、自作のPythonスクリプトを開発しました。

このスクリプトは、以下の機能を実現します:

  • 静的化:CMSからローカル環境にHTMLファイルを取得
  • リンク修正(オプション):内部リンクの変換や、一部HTML内容の変更
  • ホスティング設定:S3にアップロード

このあと、CloudFrontでHTTPS対応のホスティングを設定する作業は説明資料に従って進めてください。

スクリプトはGitHubで公開しています:

本スクリプトおよび資料は、現状のまま(AS IS)で提供されており、いかなる保証も行いません。本スクリプトの使用により発生したいかなる損害や問題についても、作成者は一切の責任を負いかねます。ご利用は自己責任でお願いいたします。

説明資料

詳細な手順はREADME.mdに記載しています。以下にもその内容を転載しておきます。


Dynamic Web to S3 Migration

このプロジェクトは、CMS管理のWebサイトからファイルをダウンロードし、Amazon S3にアップロードするためのPythonスクリプトを提供します。

また、アップロードした後に、Amazon S3をスタティック(静的)なWebサイトホスティングサービスとして構成し、Amazon CloudFrontによりCDNで配信されるようにし、AWS Certificate Manager(ACM)により生成し自動更新されるHTTPS用のSSL証明書を設定するまでの作業手順も、このREADME.mdファイルに掲載しています。

ただし、スクリプトはWindows環境で実行しているため、それ以外の環境での動作は保証できません。細かい調整が必要な場合は、スクリプトを修正することで対応してください。

※本スクリプトの実行は自己責任で行ってください。いかなる責任も負いません。また、本スクリプトにPR(プルリクエスト)やIssue(問題報告)を送られても、一切対応しませんので、あしからずご了承ください。

構成

  • requirements.txt: 必要なPythonパッケージのリスト。
  • config.ini: 認証情報を含む設定ファイル。
  • WebHtmlDownload.py: CMS管理のWebサイトから全てのHTMLファイルをダウンロードします。
  • AwsS3Upload.py: ダウンロードされたファイルをAmazon S3にアップロードします。

ログファイル

  • <トップのローカルフォルダ名>_download_log.txt: Webサイトからのダウンロードに関するログ。
  • <トップのローカルフォルダ名>_processed_log.txt: 処理済みのURLに関するログ。
  • <トップのローカルフォルダ名>_skipped_log.txt: スキップしたURLに関するログ。
  • <トップのローカルフォルダ名>_download_retry.txt: ダウンロードに失敗したURLに関するリトライ用のログ。
  • <S3名>_upload_log.txt: Amazon S3へのアップロードに関するログ。
  • <S3名>_compare_log.txt: WebサイトとAmazon S3の内容比較に関するログ。

<トップのローカルフォルダ名>(Webサイト管理用の名前)は、S3バケット名と同じ名前にします。例:wwwexamplecom

リトライ機能

※本プロジェクト開発者が試した限りでは、失敗が発生したことがないため、リトライ機能は実装済みですが、正常に稼働するかは検証されていません。

  • ダウンロードやアップロードに失敗したファイルは、リトライ用のファイルに記録されます。
  • 次回実行時にリトライ用のファイルを読み込み、前回失敗した処理を再試行します。成功した処理は再試行しません。
  • 全てのファイルが成功した場合、リトライ用のファイルは削除されます。

前提条件

CMS管理のWebサイトをWebサーバとして活用してダイナミックなWebページを配信していることを前提としています(※ただし、未検証ですがスタティックWebサイトでも有効ななずです)。また、Azure CDNなどでCDNとSSLの自動更新を対応している場合もカバーしています。

同名のAmazon S3バケットを以下の手順で作成しておいてください。

S3バケットを作る手順

作成時に以下の内容を指定することを前提とします。

  1. AWS リージョンは「アジアパシフィック (東京) ap-northeast-1」とします。
  2. AWSコンソールでS3の[汎用バケット]を開き、[バケットを作成]をクリックします。
  3. [バケットタイプ]は「汎用」を選択します。
  4. [バケット名]は<トップのローカルフォルダ名>(Webサイト管理用の名前)と同じ名前にします。例:wwwexamplecom
  5. [ACL無効]を選択してください。
  6. [パブリックアクセスをすべてブロック]のチェックを外してください。
  7. [バケットのバージョニング]は「有効にする」にしてください。
  8. [タグ - オプション]でキーは「Name」、値は「<任意のプロジェクト名(例:masahiko.info)>」でタグを追加してください。
  9. 他はデフォルトのまま[バケットを作成]をクリックしてください。
  10. これでS3バケットの作成は完了です。

必要なPythonパッケージ

以下のコマンドを使用して、必要なパッケージをインストールしてください。

pip install -r requirements.txt

認証情報の設定

AWSのアクセスキーの取得

AWSのアクセスキーはユーザーごとに取得します。セキュリティの問題もあるので、全ての作業が終わったら無効化もしくは削除するのがお勧めです。

  1. AWS Management Consoleにログインし、IAMサービスに移動します。
  2. 左側のメニューから[ユーザー]を選択します。
  3. 該当のユーザー名をクリックします。
  4. 上部の[セキュリティ認証情報]タブを開きます。
  5. [アクセスキーを作成]をクリックします。
  6. [ユースケース]は「ローカルコード」を選択します。
  7. [説明タグ値]は空のままで[アクセスキーを作成]をクリックします。
  8. これにより、アクセスキーIDとシークレットキーが発行されるので、確実にどこかに記述してください。

config.iniの編集

ご自身の環境に合わせて修正してください。

  • domainName: CMS管理Webサイトのドメイン名を指定します。例:www.example.com
  • sitemapUrlPath: Web検索用サイトマップへのルートからのパスを指定します。例:/sitemap.xml
  • topLocalName: トップのローカルフォルダ名(Webサイト管理用の名前)を指定します。S3バケット名と同じ名前にしてください。例:wwwexamplecom
  • indexFileName: インデックスドキュメント名(デフォルトのルートオブジェクト)を設定します。例:index.html
  • S3BucketName: 比較対象のS3バケット名を設定します。
  • AccessKeyId: AWSアクセスキーIDを設定します。
  • SecretAccessKey: AWSシークレットアクセスキーを設定します。
  • Region: AWSリージョンを設定します。

使用方法

WebHtmlDownload.pyの使用方法

(1) WebHtmlDownload.pyを実行して、CMS管理のWebサイトから全てのHTMLファイルをダウンロードします。

python WebHtmlDownload.py

※古い形式のサイトマップのスキーマ「http://www.google.com/schemas/sitemap/0.84」にしか対応していません。これ以外の場合、コードを修正する必要があります。

(2) ダウンロードされたファイルは、指定されたローカルディレクトリに保存されます。

AwsS3Upload.pyの使用方法

(1) AwsS3Upload.pyを実行して、ダウンロードされたファイルをAmazon S3にアップロードします。

python AwsS3Upload.py

(2) アップロードの成功または失敗はログファイルに記録されます。

全て成功すれば作業は完了です。

さらに、Favicon(Webサイト用のアイコン)もある場合は、適切な場所(例えば/favicon.ico)にAmazon S3のサイトでアップロードしてください。

S3バケットをスタティックなWebサイトホスティングサービスにするまでの手順

注意事項

  • パブリックアクセスを有効化する際はセキュリティに注意してください。不要なデータが公開されないように。
  • 公開したくないファイルはそもそもアップロードしない方がよいでしょう。このスクリプトではもともとWebサイトでパブリックに公開されていたオブジェクト(主にHTMLページ)のみを移行する仕様になっていますので、基本的には新たに不要なデータが公開されることはないはずです。

手順 1: 静的Webサイトホスティングを有効化

  1. AWSコンソールで対象のS3バケットを選択します。
  2. 上部メニューの[プロパティ]をクリックしてください。
  3. [静的Webサイトホスティング]セクションの[編集]をクリック。
  4. 「静的Webサイトホスティング」の「有効にする」を選択します。
  5. [ホスティングタイプ]jは、「静的ウェブサイトをホストする」を選択します。
  6. [インデックスドキュメント](例: index.htmldefault.html)を入力。
    • 必要なら[エラードキュメント](例: error.html)も入力。このファイルは基本的にバケットのルート(トップレベル)に配置してください。
  7. [変更の保存]をクリックします。

サンプルのerror.htmlファイルをこのプロジェクトに含めていますので、これをS3バケットのトップレベルにアップロードしてみてください。

手順 2: ブロックパブリックアクセスをオフにする

この作業は、作成時にオフにしていれば不要です。

  1. 上部メニューの[アクセス許可]をクリック。
  2. [ブロックパブリックアクセス (バケット設定)]セクションの[編集]をクリック。
  3. すべてのチェックボックスをオフにします。
  4. 保存します。
  5. 注意: この設定変更により、バケットがパブリックにアクセス可能になるリスクがあります。次のポリシー設定を適切に行いましょう。

手順 3: バケットポリシーを設定

S3バケットをパブリックにアクセス可能にするため、バケットポリシーを記載します。

以下は、特定のS3バケット(例: example-bucket)内のすべてのオブジェクトをパブリックにするポリシーです。arn:aws:s3:::example-bucketの部分は「バケット ARN」と呼ばれますが、編集画面上でコピーできます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-bucket/*"
    }
  ]
}
  1. 引き続き[アクセス許可]にある[バケットポリシー]セクションの[編集]をクリック。
  2. 上記のJSONコードを貼り付けます(example-bucketを実際のバケット名に変更)。
  3. 保存します。

手順 4: オブジェクト所有者を確認

S3バケットの[アクセス許可]で[オブジェクト所有者]が「バケット所有者の強制」となっている場合、ACL(アクセスコントロールリスト)は無効になっています。つまり、このバケット内のすべてのオブジェクトは、このアカウントによって所有されます。このバケットとそのオブジェクトへのアクセスは、ポリシーのみを使用して指定されます。

このプロジェクトでは、ACLが無効であることを前提としています。ACLが有効な場合、バケットポリシーを設定しても、オブジェクト(ファイル)がパブリックでない場合があります。

手順 5: WebサイトのURLにアクセス

スタティックWebサイトのURLは、以下の形式になります。

http://{バケット名}.s3-website-{リージョン}.amazonaws.com
http://wwwexamplecom.s3-website-ap-northeast-1.amazonaws.com
  1. 対象のS3バケットの上部メニューの[プロパティ]をクリックしてください。
  2. 一番下の[静的ウェブサイトホスティング]にある「バケットウェブサイトエンドポイント」のURLを開いてみてください。個別のオブジェクトにアクセスできるかは後で確認します。
  3. 上部メニューの[オブジェクト]から任意のオブジェクトを開いてください。
  4. 上部メニューの[プロパティ]を開き、[オブジェクトの概要]の[オブジェクト URL]を開いて、実際にWebアクセスできるかを確認してください。
  5. これによりHTMLページや画像などが正常に表示されれば、S3のスタティックなWebサイトの公開は完了です。

S3バケットのサイトがCDN(カスタムドメインSSL証明書あり)で配信されるまでの手順

Amazon CloudFrontの手順の中で、AWS Certificate Manager(ACM)を使ってカスタムドメイン用のSSL証明書を取得するようになっています。証明書の発行時にDNS検証を選択することによって、期限切れの60日前に自動更新されます。

Amazon CloudFrontの設定手順

  1. CloudFrontディストリビューションの作成

    1. AWS Management Consoleにログインし、CloudFrontサービスに移動します。
    2. [CloudFront ディストリビューションを作成]をクリックします。
    3. [Origin domain]で、S3バケットのエンドポイントを選択し、それにより表示される[Web サイトのエンドポイントを使用]をクリックします。
      • 例: - <バケット名>.s3-website-<リージョン>.amazonaws.com
    4. [名前]は自動的に入力されます。
    5. [デフォルトのキャッシュビヘイビア]セクションで[ビューワープロトコルポリシー]を「Redirect HTTP to HTTPS」に設定します。
    6. [ウェブアプリケーションファイアウォール (WAF) ]セクションで「セキュリティ保護を有効にしないでください」を選択します。追加費用を発生させないためです。必要になったらONにすればよいと思います。
    7. [設定]セクションの[料金クラス]で、日本メインなら「北米、欧州、アジア、中東、アフリカを使用」を選択します。性能と価格のバランスがよいためです。世界中からアクセスされるなら「すべてのエッジロケーションを使用する (最高のパフォーマンス)」がよいでしょう。
    8. その下の[代替ドメイン名 (CNAME) - オプション]で、[項目を追加]をクリックして、カスタムドメイン名(例:re.masahiko.info)を入力します。
    9. その下の[Custom SSL certificate - optional]で、[証明書をリクエスト]リンクをクリックします。
      • [パブリック証明書をリクエスト]を選択して[次へ]をクリックします。
      • [完全修飾ドメイン名]にカスタムドメイン名(例:re.masahiko.info)を入力します。
      • [検証方法]は「DNS 検証 - 推奨」に必ずしてください。
      • 他はデフォルトの推奨設定のままにします。
      • リソースグループで管理しやすいように[タグ]も付けるのがお勧めです。キーは「Name」として、値は「masahiko.info」など独自のグループ名を指定します。
      • [リクエスト]をクリックします。
      • [ステータス]が「保留中の検証」となるので、検証用にDNSのCNAMEの追加が必要です。お使いのDNSの設定箇所で、[ドメイン]内の表で取得できる「CNAME名」からサブドメインまでの部分(例:_abcdef123456gh7i8j9klm01n2opq345.<subdomain>)を名前として、「CNAME値」(ドメイン名で場合によっては最後の.を除いて内容、例:_a0123bcdefghigklmnopqrst45fvwxyz.zfyfvmchrl.acm-validations.aws.)を値(正規名)として指定してください。
      • 30分もしないうちに発行済みになります。[ステータス]に「発行済み」と表示されるまで待ちます。ブラウザーでリロードすると表示が変わる場合があります。
    10. CloudFrontのディストリビューション作成画面に戻ります。
    11. [Custom SSL certificate - optional]の右端の更新ボタンをクリックした後で、先ほど作成したSSLを[Custom SSL certificate - optional]で選択します。
    12. [Default root object - optional]にルート(/)でアクセスされたときに自動表示するファイル名(例: index.htmldefault.html)を入力。
    13. [ログ配信]は必要があればオンにしてください。ただし追加費用がかかるため、私の場合はオフにしています。
    14. [ディストリビューションを作成]をクリックします。
  2. CloudFrontディストリビューションのデプロイ

    • ディストリビューションのステータスが「有効」になるまで待ちます。わたしの場合はすぐでしたが、数分かかることがあるようです。
    • ディストリビューションのステータスは、CloudFrontのトップページでも確認できます。
  3. CloudFrontディストリビューションの確認

    • CloudFrontディストリビューションの[ディストリビューションドメイン名]を使用して、S3に配置したオブジェクトのパスのWebページや画像にアクセスして、無事に表示されるのを確認します(表示されるようになるまでに数分かかります)。例: d123456abcdef8.cloudfront.net
    • [ディストリビューションドメイン名]はCDN設定で使うので、保存しておいてください。

カスタムドメインのDNS設定と確認

最後にカスタムドメインでアクセスされるように設定すれば完了です。

カスタムドメインのCNAMEの内容(ドメイン名)に[ディストリビューションドメイン名]を指定してください。[ディストリビューションドメイン名]はCloudFrontで確認できます。

念のため、依然のCNAME内容は一時的に何かに書き写してバックアップしておきましょう。

反映まで1時間ほどかかります。長い場合は72時間程度も時間がかかることがあります。反映されたかはSSL証明書をブラウザから確認すればよいでしょう。もしくは以下のコマンドで確認できます。

nslookup <カスタムドメイン名>

ここまで出来たらCMS管理のWebサイトとAzure CDNの役目も終了なので、削除しても構いません。が、トラブル回避のため、72時間ほど様子を見てからの方がよいかもしれません。

全ての作業が終わったら、AWSのアクセスキーは無効化するか、削除しておきましょう。

ライセンス

このプロジェクトはApache License 2.0の下で公開されています。詳しくはLICENSEファイルをご確認ください。

Azure Blob(Webホスティング用)→S3移行を自動化! Pythonスクリプトを公開中

2024年12月、「Azure CDN from Edgioが廃止される」という突然の通知に驚き、移行作業に追われた方も多いのではないでしょうか。私もその1人でした。Webスタティックホスティング用途で「Azure Blobストレージ+Azure CDN」を複数のサイトで利用していたため、急遽、別のCDNへの移行が必要になりました。

Azure Front Doorへの移行が推奨されていますが、私の用途ではオーバースペックでコストが見合わず※1、最終的にAmazon S3+CloudFrontへの移行を選びました。その過程で、Pythonスクリプトを用いて効率よく移行を行う方法を開発しました。

※1 Azure Front Doorは高機能で優れた選択肢ですが、基本料金が高額で、小規模なWebサイトでは費用対効果が低い場合があると思います。

課題と解決策

移行作業では、AWS DataSyncも試しましたが、自由度が低く、私の求める柔軟性を満たせませんでした。そのため、自作のPythonスクリプトを使い、以下の機能を実現しました。

  • Azure Blobストレージから(ローカル環境へ)のデータ取得
  • Amazon S3へのアップロード
  • 実行時のログやエラーを管理

このあと、CloudFrontでHTTPS対応のホスティングを設定する作業は説明資料に従って進めてください。

スクリプトは以下のGitHubリポジトリで公開しています。興味がある方はぜひご覧ください。

本スクリプトおよび資料は、現状のまま(AS IS)で提供されており、いかなる保証も行いません。本スクリプトの使用により発生したいかなる損害や問題についても、作成者は一切の責任を負いかねます。ご利用は自己責任でお願いいたします。

説明資料

詳細な手順はREADME.mdに記載しています。以下にもその内容を転載しておきます。

https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png

Azure Blob to S3 Migration

このプロジェクトは、Azure Blobストレージからファイルをダウンロードし、Amazon S3にアップロードするためのPythonスクリプトを提供します。

また、アップロードした後に、Amazon S3をスタティック(静的)なWebサイトホスティングサービスとして構成し、Amazon CloudFrontによりCDNで配信されるようにし、AWS Certificate Manager(ACM)により生成し自動更新されるHTTPS用のSSL証明書を設定するまでの作業手順も、このREADME.mdファイルに掲載しています。

ただし、スクリプトはWindows環境で実行しているため、それ以外の環境での動作は保証できません。細かい調整が必要な場合は、スクリプトを修正することで対応してください。

※本スクリプトの実行は自己責任で行ってください。いかなる責任も負いません。また、本スクリプトにPR(プルリクエスト)やIssue(問題報告)を送られても、一切対応しませんので、あしからずご了承ください。

構成

  • requirements.txt: 必要なPythonパッケージのリスト。
  • config.ini: 認証情報を含む設定ファイル。
  • AzureBlobDownload.py: Azure Blobストレージからファイルをダウンロードします。
  • AwsS3Upload.py: ダウンロードされたファイルをAmazon S3にアップロードします。
  • BlobS3Compare.py: 念のため、Azure BlobストレージとAmazon S3の内容を比較します。開発者が3サイトで実施して失敗はなかったため不要かもしれません。

ログファイル

  • <Blob名>_download_log.txt: Azure Blobストレージからのダウンロードに関するログ。
  • <S3名>_upload_log.txt: Amazon S3へのアップロードに関するログ。
  • <S3名>_compare_log.txt: Azure BlobストレージとAmazon S3の内容比較に関するログ。

リトライ機能

※本プロジェクト開発者が試した限りでは、失敗が発生したことがないため、リトライ機能は実装済みですが、正常に稼働するかは検証されていません。

  • ダウンロードやアップロードに失敗したファイルは、リトライ用のファイルに記録されます。
  • 次回実行時にリトライ用のファイルを読み込み、前回失敗した処理を再試行します。成功した処理は再試行しません。
  • 全てのファイルが成功した場合、リトライ用のファイルは削除されます。

前提条件

Azure BlobストレージをWebサーバとして活用してスタティックなWebページや画像を配信していることを前提としています。また、Azure CDNなどでCDNとSSLの自動更新を対応している場合もカバーしています。

既存のAzure Blobストレージが存在するあることを前提としています。また、同名のAmazon S3バケットを以下の手順で作成しておいてください。

S3バケットを作る手順

作成時に以下の内容を指定することを前提とします。

  1. AWS リージョンは「アジアパシフィック (東京) ap-northeast-1」とします。
  2. AWSコンソールでS3の[汎用バケット]を開き、[バケットを作成]をクリックします。
  3. [バケットタイプ]は「汎用」を選択します。
  4. [バケット名]はAzure Blobストレージアカウントと同じ名前にします。例:remasahiko
  5. [ACL無効]を選択してください。
  6. [パブリックアクセスをすべてブロック]のチェックを外してください。
  7. [バケットのバージョニング]は「有効にする」にしてください。
  8. [タグ - オプション]でキーは「Name」、値は「<任意のプロジェクト名(例:masahiko.info)>」でタグを追加してください。
  9. 他はデフォルトのまま[バケットを作成]をクリックしてください。
  10. これでS3バケットの作成は完了です。

必要なPythonパッケージ

以下のコマンドを使用して、必要なパッケージをインストールしてください。

pip install -r requirements.txt

認証情報の設定

Azure Blobストレージアカウントの接続文字列の取得

  1. Azureで対象のストレージアカウントを開き、左のメニューから[セキュリティとネットワーク]-[アクセスキー]を選択します。
  2. [接続文字列]をコピーします。

AWSのアクセスキーの取得

AWSのアクセスキーはユーザーごとに取得します。セキュリティの問題もあるので、全ての作業が終わったら無効化もしくは削除するのがお勧めです。

  1. AWS Management Consoleにログインし、IAMサービスに移動します。
  2. 左側のメニューから[ユーザー]を選択します。
  3. 該当のユーザー名をクリックします。
  4. 上部の[セキュリティ認証情報]タブを開きます。
  5. [アクセスキーを作成]をクリックします。
  6. [ユースケース]は「ローカルコード」を選択します。
  7. [説明タグ値]は空のままで[アクセスキーを作成]をクリックします。
  8. これにより、アクセスキーIDとシークレットキーが発行されるので、確実にどこかに記述してください。

config.iniの編集

ご自身の環境に合わせて修正してください。

  • ConnectionString: Azure Blob Storageの接続文字列を設定します。
  • BlobStorageName: Blobストレージ名を指定します。
  • S3BucketName: 比較対象のS3バケット名を設定します。
  • AccessKeyId: AWSアクセスキーIDを設定します。
  • SecretAccessKey: AWSシークレットアクセスキーを設定します。
  • Region: AWSリージョンを設定します。

使用方法

AzureBlobDownload.pyの使用方法

(1) AzureBlobDownload.pyを実行して、Azure Blobストレージからファイルをダウンロードします。

python AzureBlobDownload.py

注意点として、パブリックアクセスが 'container' 以外のコンテナ(プライベートやBLOBなど)はスキップする仕様なので注意してください。必要があればプログラムを書き換えてください。

(2) ダウンロードされたファイルは、指定されたローカルディレクトリに保存されます。

AwsS3Upload.pyの使用方法

(1) AwsS3Upload.pyを実行して、ダウンロードされたファイルをAmazon S3にアップロードします。

python AwsS3Upload.py

(2) アップロードの成功または失敗はログファイルに記録されます。

BlobS3Compare.pyの使用方法

(1) BlobS3Compare.pyを実行して、Azure BlobストレージとAmazon S3の内容を比較します。

python BlobS3Compare.py

(2) 比較の結果はログファイルに記録されます。

全て成功すれば作業は完了です。

S3バケットをスタティックなWebサイトホスティングサービスにするまでの手順

注意事項

  • パブリックアクセスを有効化する際はセキュリティに注意してください。不要なデータが公開されないように。
  • 公開したくないファイルはそもそもアップロードしない方がよいでしょう。このスクリプトではもともとAzure Blobストレージでパブリックに公開されていたBlobのみを移行する仕様になっていますので、基本的には新たに不要なデータが公開されることはないはずです。

手順 1: 静的Webサイトホスティングを有効化

  1. AWSコンソールで対象のS3バケットを選択します。
  2. 上部メニューの[プロパティ]をクリックしてください。
  3. [静的Webサイトホスティング]セクションの[編集]をクリック。
  4. 「静的Webサイトホスティング」の「有効にする」を選択します。
  5. [ホスティングタイプ]jは、「静的ウェブサイトをホストする」を選択します。
  6. [インデックスドキュメント](例: index.htmldefault.html)を入力。
    • 必要なら[エラードキュメント](例: error.html)も入力。このファイルは基本的にバケットのルート(トップレベル)に配置してください。
  7. [変更の保存]をクリックします。

サンプルのerror.htmlファイルをこのプロジェクトに含めていますので、これをS3バケットのトップレベルにアップロードしてみてください。

手順 2: ブロックパブリックアクセスをオフにする

この作業は、作成時にオフにしていれば不要です。

  1. 上部メニューの[アクセス許可]をクリック。
  2. [ブロックパブリックアクセス (バケット設定)]セクションの[編集]をクリック。
  3. すべてのチェックボックスをオフにします。
  4. 保存します。
  5. 注意: この設定変更により、バケットがパブリックにアクセス可能になるリスクがあります。次のポリシー設定を適切に行いましょう。

手順 3: バケットポリシーを設定

S3バケットをパブリックにアクセス可能にするため、バケットポリシーを記載します。

以下は、特定のS3バケット(例: example-bucket)内のすべてのオブジェクトをパブリックにするポリシーです。arn:aws:s3:::example-bucketの部分は「バケット ARN」と呼ばれますが、編集画面上でコピーできます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::example-bucket/*"
    }
  ]
}
  1. 引き続き[アクセス許可]にある[バケットポリシー]セクションの[編集]をクリック。
  2. 上記のJSONコードを貼り付けます(example-bucketを実際のバケット名に変更)。
  3. 保存します。

手順 4: オブジェクト所有者を確認

S3バケットの[アクセス許可]で[オブジェクト所有者]が「バケット所有者の強制」となっている場合、ACL(アクセスコントロールリスト)は無効になっています。つまり、このバケット内のすべてのオブジェクトは、このアカウントによって所有されます。このバケットとそのオブジェクトへのアクセスは、ポリシーのみを使用して指定されます。

このプロジェクトでは、ACLが無効であることを前提としています。ACLが有効な場合、バケットポリシーを設定しても、オブジェクト(ファイル)がパブリックでない場合があります。

手順 5: WebサイトのURLにアクセス

スタティックWebサイトのURLは、以下の形式になります。

http://{バケット名}.s3-website-{リージョン}.amazonaws.com
http://remasahiko.s3-website-ap-northeast-1.amazonaws.com
  1. 対象のS3バケットの上部メニューの[プロパティ]をクリックしてください。
  2. 一番下の[静的ウェブサイトホスティング]にある「バケットウェブサイトエンドポイント」のURLを開いてみてください。個別のオブジェクトにアクセスできるかは後で確認します。
  3. 上部メニューの[オブジェクト]から任意のオブジェクトを開いてください。
  4. 上部メニューの[プロパティ]を開き、[オブジェクトの概要]の[オブジェクト URL]を開いて、実際にWebアクセスできるかを確認してください。
  5. これによりHTMLページや画像などが正常に表示されれば、S3のスタティックなWebサイトの公開は完了です。

S3バケットのサイトがCDN(カスタムドメインSSL証明書あり)で配信されるまでの手順

Amazon CloudFrontの手順の中で、AWS Certificate Manager(ACM)を使ってカスタムドメイン用のSSL証明書を取得するようになっています。証明書の発行時にDNS検証を選択することによって、期限切れの60日前に自動更新されます。

Amazon CloudFrontの設定手順

  1. CloudFrontディストリビューションの作成

    1. AWS Management Consoleにログインし、CloudFrontサービスに移動します。
    2. [CloudFront ディストリビューションを作成]をクリックします。
    3. [Origin domain]で、S3バケットのエンドポイントを選択し、それにより表示される[Web サイトのエンドポイントを使用]をクリックします。
      • 例: - <バケット名>.s3-website-<リージョン>.amazonaws.com
    4. [名前]は自動的に入力されます。
    5. [デフォルトのキャッシュビヘイビア]セクションで[ビューワープロトコルポリシー]を「Redirect HTTP to HTTPS」に設定します。
    6. [ウェブアプリケーションファイアウォール (WAF) ]セクションで「セキュリティ保護を有効にしないでください」を選択します。追加費用を発生させないためです。必要になったらONにすればよいと思います。
    7. [設定]セクションの[料金クラス]で、日本メインなら「北米、欧州、アジア、中東、アフリカを使用」を選択します。性能と価格のバランスがよいためです。世界中からアクセスされるなら「すべてのエッジロケーションを使用する (最高のパフォーマンス)」がよいでしょう。
    8. その下の[代替ドメイン名 (CNAME) - オプション]で、[項目を追加]をクリックして、カスタムドメイン名(例:re.masahiko.info)を入力します。
    9. その下の[Custom SSL certificate - optional]で、[証明書をリクエスト]リンクをクリックします。
      • [パブリック証明書をリクエスト]を選択して[次へ]をクリックします。
      • [完全修飾ドメイン名]にカスタムドメイン名(例:re.masahiko.info)を入力します。
      • [検証方法]は「DNS 検証 - 推奨」に必ずしてください。
      • 他はデフォルトの推奨設定のままにします。
      • リソースグループで管理しやすいように[タグ]も付けるのがお勧めです。キーは「Name」として、値は「masahiko.info」など独自のグループ名を指定します。
      • [リクエスト]をクリックします。
      • [ステータス]が「保留中の検証」となるので、検証用にDNSのCNAMEの追加が必要です。お使いのDNSの設定箇所で、[ドメイン]内の表で取得できる「CNAME名」からサブドメインまでの部分(例:_abcdef123456gh7i8j9klm01n2opq345.<subdomain>)を名前として、「CNAME値」(ドメイン名で場合によっては最後の.を除いて内容、例:_a0123bcdefghigklmnopqrst45fvwxyz.zfyfvmchrl.acm-validations.aws.)を値(正規名)として指定してください。
      • 30分もしないうちに発行済みになります。[ステータス]に「発行済み」と表示されるまで待ちます。ブラウザーでリロードすると表示が変わる場合があります。
    10. CloudFrontのディストリビューション作成画面に戻ります。
    11. [Custom SSL certificate - optional]の右端の更新ボタンをクリックした後で、先ほど作成したSSLを[Custom SSL certificate - optional]で選択します。
    12. [Default root object - optional]にルート(/)でアクセスされたときに自動表示するファイル名(例: index.htmldefault.html)を入力。
    13. [ログ配信]は必要があればオンにしてください。ただし追加費用がかかるため、私の場合はオフにしています。
    14. [ディストリビューションを作成]をクリックします。
  2. CloudFrontディストリビューションのデプロイ

    • ディストリビューションのステータスが「有効」になるまで待ちます。わたしの場合はすぐでしたが、数分かかることがあるようです。
    • ディストリビューションのステータスは、CloudFrontのトップページでも確認できます。
  3. CloudFrontディストリビューションの確認

    • CloudFrontディストリビューションの[ディストリビューションドメイン名]を使用して、S3に配置したオブジェクトのパスのWebページや画像にアクセスして、無事に表示されるのを確認します(表示されるようになるまでに数分かかります)。例: d123456abcdef8.cloudfront.net
    • [ディストリビューションドメイン名]はCDN設定で使うので、保存しておいてください。

カスタムドメインのDNS設定と確認

最後にカスタムドメインでアクセスされるように設定すれば完了です。

カスタムドメインのCNAMEの内容(ドメイン名)に[ディストリビューションドメイン名]を指定してください。[ディストリビューションドメイン名]はCloudFrontで確認できます。

念のため、依然のCNAME内容は一時的に何かに書き写してバックアップしておきましょう。

反映まで1時間ほどかかります。長い場合は72時間程度も時間がかかることがあります。反映されたかはSSL証明書をブラウザから確認すればよいでしょう。もしくは以下のコマンドで確認できます。

nslookup <カスタムドメイン名>

ここまで出来たらAzure BlobストレージとAzure CDNの役目も終了なので、削除しても構いません。が、トラブル回避のため、72時間ほど様子を見てからの方がよいかもしれません。

全ての作業が終わったら、AWSのアクセスキーは無効化するか、削除しておきましょう。

ライセンス

このプロジェクトはApache License 2.0の下で公開されています。詳しくはLICENSEファイルをご確認ください。

AI/機械学習/データサイエンス関連の検定・資格の取得履歴

合格証明証を表示する場所もないので、このエントリに貼り付けていくことにしました。

ちなみに「gacco(統計学/サイエンス/AI・機械学習)の修了証」というページもあります。

Google データアナリティクス プロフェッショナル認定証

Google データアナリティクス プロフェッショナル認定証

マナビDX Quest:2022年度 第1ターム ケーススタディ教育プログラムGold修了証 (データ駆動型の変革推進の疑似体験)

マナビDX Quest:2022年度 第1ターム ケーススタディ教育プログラムGold修了証 (データ駆動型の変革推進の疑似体験)

データサイエンティスト検定 リテラシーレベル 2022

データサイエンティスト検定 リテラシーレベル 2022

JDLA Deep Learning for GENERAL 2017

JDLA Deep Learning for GENERAL 2017

統計検定2級

統計検定2級

オープンバッジ形式の合格証明書

ミニぷぱ(Mini Pupper)の日本向け販売サイトとROSを学ぶお勧め教材

ミニぷぱの日本向け公式販売サイトがオープンしたようです。

MangDang JP Shop

こちらの公式ツイートによると、2022年6月1日~15日で特別キャンペーンをやっているようです。30%オフとお安く入手できるチャンスです。初日(2022年6月1日?)のみのプレゼントもあるようです。

自分は入手済みなのでもう購入しないですが...。

Mini Pupper V2情報

上記はミニぷぱ「V1」の販売情報ですが、この記事を書いた本日、「V2」の情報が出てきています。詳しくは下記のツイートを参照してください。

「Fly in the sky?」とドローン的に飛べるようになるような感じで書かれていますね。AI機能も強化されそうです。以下にV1とV2の比較表を引用しておきます。

Mini Pupper V1とV2の比較表(@LeggedRobotのツイートから引用)

これは欲しい。OSは最新のUbuntu 22.04 LTSになり、ミドルウェアのロボット用プラットフォームはROS 2になるようです。V2は年末までにローンチされて出荷開始される計画とのこと。楽しみですね。それまでの練習にV1を購入して、ROSを学んでおくのもよいと思います。ROS 1の知識はROS 2でもある程度有効なようなので。

お勧めのROS 1書籍

ミニぷぱV1では下記の2本の記事を執筆しました。これ以上は書く予定はなく、V2待ちです。

これを書くに当たってROSはミニぷぱの開発を試しながら理解していったのですが、下記の書籍『ROSではじめるロボットプログラミング[改訂版] (I/O BOOKS)』を参考にしました(※2021/10/26発売の「改訂版」であることに注意)。

あらためて今日、最初から最後まで読み通しましたが、開発しながらコードや公式ドキュメント、ネット情報から調べて分かったことが全てこの本に書いていました...。本屋さんでこの本を選んだので、これ以外のROS本は読んでいませんが、他の人のコメントを読んでもROS初心者向けの最初の1冊として他の書籍よりもよさそうです。ROS 1を学ぶ人にわたしもお勧めします。

また、上記の2本目の記事もコードコメントの形で重要な内容を含めているので、そちらを読むだけでもROSの理解は広がるかなと思います。

ミニぷぱ(Mini Pupper)のキャリブレーションの「こつ」

ミニぷぱ(Mini Pupper)のキャリブレーションは意外に失敗しやすいポイントです。ここで失敗するとうまく走行できなかったりこけやすかったりします。実際に私も最初はキャリブレーションに失敗してこけやすく仕上がってしまい、サポートに問い合わせました。

まず、キャリブレーションには、

  • 45°(新しいバージョン)
  • 90°(古いバージョン)

の2種類の角度があります。PS4版のキャリブレーション時に、公式マニュアル通りにやると45°のキャリブレーションをするようになっていますが、これが難しい。しかし慣れた今ではコツが分かるので紹介します。

あと、PS4版のマニュアル通りにやったつもりでしたが、なぜか90°でキャリブレーションしなければなかったです。これもキャリブレーションに失敗した理由なのですが。

最新のPS4版のソースコードでは45°になっています。個人的には90°がキャリブレーションしやすいと思いましたが、開発元のMangDang社によると「45°が分かりやすい」という意見が多数でこれに決定したとのことでした。

これもかなり慣れてから気付いたこですが、OSイメージをダウンロードできる場所が、

このように複数あります。新しいOSイメージをダウンロードするように気を付けましょう。

45°のキャリブレーションの「こつ」

具体的には下の図のようになります。図は公式マニュアル「ソフトウェア — Mini Pupper 1.0.0-alpha ドキュメント」から引用した画像を少し加工したものです。

45°のキャリブレーションのこつ(公式マニュアルから引用して加工)

特に重要なのが(1)です。各足の接地点がモーターの軸の完全に真下にすることでこけることがほぼ無くなりました。マニュアルでは45°が強調されていますが、わたしの感想ではこの点が重要で、あとは(2)の関節部分を90°にすればよいだけです。これだけです。45°の分度器は不要です。

90°のキャリブレーションの「こつ」

もう一方の90°の方は簡単です。具体的には下の図のようになります。図は公式マニュアル「SLAM・ナビゲーション — Mini Pupper 1.0.0-alpha ドキュメント」から引用した画像を少し加工したものです。

90°のキャリブレーションのこつ(公式マニュアルから引用して加工)

単純なキャリブレーションは90°の方が簡単だと思いますが、実際の走行バランスが正確に取れることを考えると、確かに45°でキャリブレーションするのが一番いいですね。

「ミニぷぱの走行バランスがおかしい」「ミニぷぱがこけやすい」という人は、ミニぷぱが静止して起立した状態で、上の45°の状態になっているかを確認してみるとよいと思います。

ミニぷぱ(Mini Pupper)のPS4版/ROS版のキャリブレーションデータ

ミニぷぱでキャリブレーションをしたとき、のPS4版/ROS版ではデータの保存先が異なります。

PS4版

/home/ubuntu/Robotics/QuadrupedRobot/StanfordQuadruped/calibrate_tool.pyファイルの内容を確認するのが一番良いです。

コードを読むと、Raspberry Pi 4 Model Bボード上のEEPROM(不揮発性メモリ)に格納されています。これにより、PS4版のOSのmicroSDカードを差し替えても、キャリブレーションデータが引き継がれます。

このデータをROS版でも読み取ってくれればよいのですが、ROS版はファイルで管理されているようです。

ROS版

こちらは/home/ubuntu/catkin_ws/src/minipupper_ros/servo_interface/scripts/calibrate.pyファイルの内容を確認してください。

コードを読むと、/home/ubuntu/catkin_ws/src/minipupper_ros/servo_interface/config/calibration/calibration.yamlファイルとして保存されています。よって、ROS版のOSのmicroSDカードを差し替える場合は、このファイルをコピペすれば引き継げるのではないかと思います(やったことがないので不明)。

どちらかに統一してほしいけど、YAMLファイルの方が取り扱いはしやすいですね。

ROS版にはPS4版のようにGUIで作業できるキャリブレーションツールがありません。PS4版のキャリブレーションツールをROS版で使っても、EEPROMに保存されるだけなので意味がありません。キャリブレーションツールのコードは難しく無さそうなので、ROS版用に修正するということも不可能ではないのですが、そこまでするのは面倒なのですよね。

ミニぷぱ(Mini Pupper)ROS版のRaspberry Pi 4 Model BのGPIOピン

非常にニッチだと思いますが、ミニぷぱのROS版のGPIOピンの情報を共有します。

※書く必要もないと思いますが念のため。この記事の通りに実施して何か起きた場合の責任は筆者および本サイトは負いません。自己責任でお願いします。

GPIOピン

ミニぷぱのROS版でGPIOピンがどのように使われているかはコードを追いかけて調べるしかありません(たぶん、資料がなさそうです)。書き方が雑ですが、自分がコード上に書いたものをコピペしたためです。

自分がコードを調べてチェックした限りでは以下のように使われいるようでした。※勘違いや間違いがあるかもしれないので、あくまでヒントとして参照してください。

# - GPIO0 : ID_SD <Serial Data for HAT for EEPROM>
# - GPIO1 : ID_SC <Serial Clock for HAT for EEPROM>
# - GPIO2 : I2C SDA <Inter-Integrated Circuit> <Serial Data>
# - GPIO3 : I2C SCL <Serial Clock>
# - GPIO4 : "[Leg4]Left-Front-Calf" GPCLK0 <General Purpose Clock>
# - GPIO5 : "[Leg4]Left-Front-Thigh" GPCLK1
# - GPIO6 : "[Leg4]Left-Front-Hip" GPCLK2
# - GPIO7 : "[Leg3]Right-Back-Calf" SPI CE0 <Serial Peripheral Interface> <Chip Enable>
# - GPIO8 : "[Leg3]Right-Back-Thigh" SPI CE1
# - GPIO9 : "[Leg3]Right-Back-Hip" SPI MISO <Master In Slave Out>
# - GPIO10: "[Leg2]Left-Fore-Calf" SPI MOSI <Master Out Slave In>
# - GPIO11: "[Leg2]Left-Fore-Thigh" SPI SCLK <Serial Clock>
# - GPIO12: "[Leg2]Left-Fore-Hip" PWM0 <Pulse Width Modulation>
# - GPIO13: "[Leg1]Right-Fore-Calf" PWM1
# - GPIO14: "[Leg1]Right-Fore-Thigh "UART TXD <Universal Asynchronous Receiver Transmitter> <Transmit Data>
# - GPIO15: "[Leg1]Right-Fore-Hip" UART RXD <Receive Data>
# - GPIO16: "Battery Buzzer"
# - GPIO17: 
# - GPIO18: PCM_CLK <Pulse Code Modulation> <PCM Clock>
# - GPIO19: PCM_FS <PCM Frame Sync>
# - GPIO20: PCM_DIN <PCM Data In>
# - GPIO21: "Servo 2 control" PCM_DOUT <PCM Data Out>
# - GPIO22: 
# - GPIO23: 
# - GPIO24: "LCD RST <ReSeT control>"
# - GPIO25: "Servo 1 control"
# - GPIO26: "LCD LED <backlight LED control>" <for input>
# - GPIO27: "LCD DC <Data/Command (NOT MOSI!)>" <for output>

Raspberry Piの40ピン構成:

# 40-pins configuration of Raspberry Pi:
#    3V3  (1) (2)  5V
#  GPIO2  (3) (4)  5V
#  GPIO3  (5) (6)  GND
#  GPIO4  (7) (8)  GPIO14
#    GND  (9) (10) GPIO15
# GPIO17 (11) (12) GPIO18
# GPIO27 (13) (14) GND
# GPIO22 (15) (16) GPIO23
#    3V3 (17) (18) GPIO24
# GPIO10 (19) (20) GND
#  GPIO9 (21) (22) GPIO25
# GPIO11 (23) (24) GPIO8
#    GND (25) (26) GPIO7
#  GPIO0 (27) (28) GPIO1
#  GPIO5 (29) (30) GND
#  GPIO6 (31) (32) GPIO12
# GPIO13 (33) (34) GND
# GPIO19 (35) (36) GPIO16
# GPIO26 (37) (38) GPIO20
#    GND (39) (40) GPIO21