カテゴリー: tech

  • サブモジュールによるGitリポジトリの引っ越しトラブルとその解決方法

    サブモジュールによるGitリポジトリの引っ越しトラブルとその解決方法

    概要

    Gitリポジトリの移行を行う際、サブモジュールに関する問題が発生することがあります。今回、別のリポジトリへ引っ越しを行った際に「Subproject commit 03311a1」のようなメッセージがpush後に表示され、期待していたファイルがリポジトリに含まれていないというトラブルに遭遇しました。

    本記事では、サブモジュール関連の問題を解決する手順を詳しく解説します。サブモジュールの取り扱いや、リポジトリ移行時のトラブル解決に役立つ知識を提供します。

    サブモジュールとは?

    Gitサブモジュールとは、あるGitリポジトリの中に、別のGitリポジトリをリンクさせる仕組みです。サブモジュールを使用することで、1つのリポジトリの中で複数のプロジェクトや依存関係を管理できます。

    たとえば、メインプロジェクトの中に、依存するライブラリやモジュールを外部リポジトリとして含めたい場合にサブモジュールが利用されます。

    サブモジュールの管理には .gitmodules という設定ファイルが使われ、サブモジュールの参照先やパスがここに記録されます。しかし、これがリポジトリの移行時に思わぬ問題を引き起こすことがあります。

    今回の問題の原因

    今回の問題は、リポジトリ移行時にサブモジュールを適切に処理しなかったために発生しました。具体的には、以下の操作を行った後に問題が起きました。

    find ./ -name .git
    rm -rf ./product-server/.git ./product-infrastructure/.git ./product-client/.git

    .gitディレクトリを削除することで、サブモジュールの追跡情報が失われた状態になり、Gitはサブモジュールをコミットする代わりに、サブモジュールの参照(SHA-1ハッシュ)だけを記録しました。その結果、pushした際に「Subproject commit …」のメッセージが表示され、ファイル自体がリポジトリに含まれない事態が発生したのです。

    具体的な解決手順

    サブモジュールが原因でリポジトリにファイルが含まれない場合、以下の手順で解決できます。

    1. サブモジュールの確認

    まず、サブモジュールのパスや参照を確認する必要があります。

    git ls-files --stage
    

    これにより、サブモジュールが存在する場合、その参照情報(160000)が表示されます。以下は出力例です。

    160000 03311a1 0	product-server
    

    160000 はサブモジュールを示しており、サブモジュールのパスが product-server であることがわかります。

    2. サブモジュールの解除

    サブモジュールを通常のディレクトリとして扱うためには、サブモジュールの参照を解除します。

    # サブモジュールの解除
    git rm --cached product-server
    
    # サブモジュールの実体を削除
    rm -rf product-server/.git
    
    # コミットとpush
    git add .
    git commit -m "Remove submodule and add product-server as regular directory"
    git push origin main
    

    この手順をサブモジュールごとに繰り返します。

    3. .gitmodules の確認と削除

    サブモジュールが定義されている場合、.gitmodules ファイルも存在する可能性があります。このファイルを削除する必要がある場合があります。

    rm .gitmodules
    git add .
    git commit -m "Remove .gitmodules"
    git push origin main
    

    これでサブモジュールの参照は解除され、通常のディレクトリとしてリポジトリに追加されます。

    解決までのまとめ

    今回のケースでは、サブモジュールがリポジトリ移行の際に適切に扱われなかったため、サブモジュールの参照だけが残り、実際のファイルがpushされないという問題が発生しました。この問題を解決するためには、以下の手順が必要でした。

    1. サブモジュールの参照を確認git ls-files --stage で確認。
    2. サブモジュールの解除git rm --cached <サブモジュール名> で解除。
    3. 通常のディレクトリとして追加.git フォルダを削除し、再コミット。

    これらのステップを踏むことで、サブモジュールを含むリポジトリの引っ越しを無事に完了させることができました。

  • Amazon ECS Exec チェッカーを使用してもログインできない場合の対処

    Amazon ECS Exec チェッカーを使用してもログインできない場合の対処

    はじめに

    Amazon ECS(Elastic Container Service)は、コンテナ化されたアプリケーションのデプロイ、管理、スケーリングを簡素化するためのサービスです。しかし、ECS Exec機能を利用してコンテナにアクセスする際に、想定通りに動作しない場合があります。本記事では、Amazon ECS Exec チェッカーを使用しても異常が見られなかったが、依然としてログインできない場合の対処法について解説します。

    調査したこと

    以下の手順に従って、Amazon ECS Exec チェッカーを使用してテストを行いました。実行結果は以下の通りです。

    https://github.com/aws-containers/amazon-ecs-exec-checker

    $ ./check-ecs-exec.sh $cluster $task

    -------------------------------------------------------------
    Prerequisites for check-ecs-exec.sh v0.7
    -------------------------------------------------------------
    jq | OK (/usr/local/bin/jq)
    AWS CLI | OK ([xx]/aws)

    -------------------------------------------------------------
    Prerequisites for the AWS CLI to use ECS Exec
    -------------------------------------------------------------
    AWS CLI Version | OK (aws-cli/1.22.7 Python/3.7.2 Darwin/23.4.0 botocore/1.23.7)
    Session Manager Plugin | OK (1.2.463.0)

    -------------------------------------------------------------
    Checks on ECS task and other resources
    -------------------------------------------------------------
    Region : [xxx]
    Cluster: [xxx]
    Task : [xxx]
    -------------------------------------------------------------
    Cluster Configuration | Audit Logging Not Configured
    Can I ExecuteCommand? | [xxx]
    ecs:ExecuteCommand: allowed
    ssm:StartSession denied?: allowed
    Task Status | RUNNING
    Launch Type | Fargate
    Platform Version | 1.4.0
    Exec Enabled for Task | OK
    Container-Level Checks |
    ----------
    Managed Agent Status
    ----------
    1. RUNNING for "postfix"
    2. RUNNING for "http"
    3. RUNNING for "composer"
    4. RUNNING for "log-router"
    ----------
    Init Process Enabled ([xxx]:241)
    ----------
    1. Enabled - "http"
    2. Enabled - "composer"
    3. Enabled - "postfix"
    4. Disabled - "log-router"
    ----------
    Read-Only Root Filesystem ([xxx]:241)
    ----------
    1. Disabled - "http"
    2. Disabled - "composer"
    3. Disabled - "postfix"
    4. Disabled - "log-router"
    Task Role Permissions | [xxx]
    ssmmessages:CreateControlChannel: allowed
    ssmmessages:CreateDataChannel: allowed
    ssmmessages:OpenControlChannel: allowed
    ssmmessages:OpenDataChannel: allowed
    VPC Endpoints | SKIPPED ([xxx] - No additional VPC endpoints required)
    Environment Variables | ([xxx]:241)
    1. container "http"
    - AWS_ACCESS_KEY: not defined
    - AWS_ACCESS_KEY_ID: not defined
    - AWS_SECRET_ACCESS_KEY: not defined
    2. container "composer"
    - AWS_ACCESS_KEY: not defined
    - AWS_ACCESS_KEY_ID: not defined
    - AWS_SECRET_ACCESS_KEY: not defined
    3. container "postfix"
    - AWS_ACCESS_KEY: not defined
    - AWS_ACCESS_KEY_ID: not defined
    - AWS_SECRET_ACCESS_KEY: not defined
    4. container "log-router"
    - AWS_ACCESS_KEY: not defined
    - AWS_ACCESS_KEY_ID: not defined
    - AWS_SECRET_ACCESS_KEY: not defined

    上記の結果より、Amazon ECS Exec チェッカーを使用しても異常は見られませんでした。

    すべてのチェックが問題なくパスしていることが確認できました。

    結論と対処法

    Amazon ECS Exec チェッカーを使用しても異常が見られなかったにもかかわらず、依然としてECS Execを利用してコンテナにログインできない原因は、タスク定義における pidModetask に設定されているためであると判断しました。

    pidMode の設定変更

    pidModetask から container に変更することで、この問題を解決できます。以下の手順で設定を変更してください:

    1. タスク定義の確認と編集: AWSコンソールまたはAWS CLIを使用して、問題のタスク定義を確認します。タスク定義のJSON内でpidModetaskに設定されている箇所を見つけ、該当行を削除


    2. タスクの再デプロイ: タスク定義を更新後、新しいタスク定義を使用してタスクを再デプロイします。これにより、更新された設定が適用されます。
    3. ECS Execの再試行: 設定変更後、再度ECS Execを試行して、コンテナへのアクセスが可能か確認します。

    参考情報

    https://github.com/aws/containers-roadmap/issues/2268

    まとめ

    Amazon ECS Exec チェッカーを使用しても異常が見られない場合でも、タスク定義の設定によってはECS Execが正常に動作しないことがあります。特にpidModeの設定に注意が必要です。本記事が、ECS Execのトラブルシューティングに役立つことを願っています。

  • Go 開発環境: GOROOT、GOPATH、および VSCode 設定の理解

    Go 開発環境: GOROOT、GOPATH、および VSCode 設定の理解

    Go の開発環境を設定する際に、特に VSCode や asdf を使用する場合は、GOROOTGOPATH の役割を理解し、正しく設定することが重要です。
    この記事では、これらのコンポーネントとその関係を整理し、スムーズな開発環境を実現するための設定方法を説明します。

    GOROOT: Go のインストールディレクトリ

    定義: GOROOT は、Go がインストールされているディレクトリを指す環境変数です。Go のバイナリ、標準ライブラリのソースコード、およびコンパイラツールが含まれています。

    目的: GOROOT は Go のツールチェーンに対して、コアライブラリやバイナリの場所を教える役割を果たします。Go をインストールすると自動的に設定されるため、通常は変更する必要はありません。ただし、複数の Go バージョンをインストールしている場合は設定が必要です。

    :asdf を使って Go のバージョン 1.22.1 をインストールした場合、GOROOT は次のようになります。

    /Users/your.name/.asdf/installs/golang/1.22.1/go

    GOPATH: ワークスペースディレクトリ

    定義: GOPATH は、Go のコード、依存関係、およびバイナリが保存されるワークスペースのルートを指定する環境変数です。

    目的: GOPATH は、Go のツールチェーンに対してプロジェクトのソースコードやサードパーティパッケージのインストール場所を教えます。GOROOT とは異なり、GOPATH は任意のディレクトリに設定できます。

    : 一般的な GOPATH の設定は次のようになります。

    /Users/your.name/go

    VSCode 設定: GOROOT と GOPATH の設定

    VSCode を使用して Go の開発を行う場合、エディタに対して Go のインストール場所(GOROOT)とワークスペース(GOPATH)を知らせる設定が必要です。

    VSCode 設定:

    • go.goroot: この設定は VSCode に Go のインストール場所を教えます。asdf が管理する Go のインストールパス内の go ディレクトリを指す必要があります。
    • go.gopath: この設定は VSCode に Go のワークスペースの場所を教えます。GOPATH に設定したディレクトリを指します。

    設定例:

    { "go.gopath": "/Users/your.name/go", "go.goroot": "/Users/your.name/.asdf/installs/golang/1.22.1/go" }

    なぜ GOROOT と GOPATH は異なるパスなのか?

    GOROOTGOPATH は異なる目的を持つため、別々のパスを設定する必要があります。

    • GOROOT は Go のインストール自体を指します。Go コンパイラ、標準ライブラリ、ツールチェーンが含まれています。
    • GOPATH は個人の Go ワークスペースを指します。プロジェクトのソースコード、ダウンロードした依存関係、ビルドしたバイナリが含まれます。

    asdf を使用すると、複数の Go バージョンを管理できますが、それぞれのバージョンに対して GOROOT が異なります。一方、GOPATH は一貫して個人のワークスペースを指します。

    実際の設定例: 環境のセットアップ

    1. Go のインストール(asdf を使用):
      asdf install golang 1.22.1
      asdf global golang 1.22.1
    2. 環境変数の設定: シェルの設定ファイル(~/.bashrc, ~/.zshrc など)に以下を追加します。

      export GOROOT=$HOME/.asdf/installs/golang/1.22.1/go export GOPATH=$HOME/go export PATH=$GOROOT/bin:$PATH
    3. VSCode の設定: settings.json を開き、次の設定を追加します。

      { "go.gopath": "/Users/your.name/go", "go.goroot": "/Users/your.name/.asdf/installs/golang/1.22.1/go" }

    結論

    GOROOTGOPATH の違いと、それを VSCode に設定する方法を理解することは、スムーズな Go 開発環境を構築するために非常に重要です。これらのパスを正しく設定することで、Go のツールやエディタが必要なファイルや依存関係を正しく見つけることができ、設定に関連するエラーのリスクを減らすことができます。

    詳細については、公式の Go ドキュメント「Go 開発環境のセットアップ」を参照してください。

  • Dockerを使ってMySQL 8.0をパスワードなしでローカル接続する

    Dockerを使ってMySQL 8.0をパスワードなしでローカル接続する

    以下の手順で、MySQL 8.0をDockerで起動し、パスワードなしでローカル接続できるように設定する方法を説明します。

    手順 1: Dockerコンテナの起動

    まず、パスワードなしでMySQLコンテナを起動します。MYSQL_ALLOW_EMPTY_PASSWORD環境変数をyesに設定します。

    docker run --name mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -d -p 3306:3306 mysql:8.0

    このコマンドは、以下のことを行います:

    1. mysqlという名前のコンテナを作成
    2. MySQLのルートユーザーのパスワードを空に設定
    3. コンテナをバックグラウンドで実行
    4. ローカルの3306ポートをコンテナの3306ポートにマッピング

    手順 2: MySQLクライアントで接続

    次に、ローカルのMySQLクライアントを使ってMySQLサーバーに接続します。パスワードなしで接続するために、-pオプションを省略します。

    mysql -h 127.0.0.1 -P 3306 -u root

    注: mysql のコンテナが立ち上がるまでの間

    ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 2

    というエラーが表示されます。その際数秒待って再度接続を試みてください。

    トラブルシューティング

    コンテナが正しく起動しているか確認:

    docker ps -a

    コンテナのログを確認:

    docker logs mysql

    MySQLサーバーが正しく起動していない場合、ログを確認してエラーメッセージをチェックし、適切な対策を講じてください。

  • ローカル環境でHTTPSサーバーを立ち上げる

    ローカル環境でHTTPSサーバーを立ち上げる

    OpenSSLとNode.jsの http-server モジュールを使って、ローカル環境でHTTPSサーバーを立ち上げる方法を説明。

    Subject Alternative Name (SAN) を設定する

    vim SAN.txt
    ---
    subjectAltName = DNS:sumito.jp

    この手順では、SANを指定するためのファイル SAN.txt を作成します。ここでは sumito.jp をSANとして指定していますが、適宜変更してください。

    秘密鍵と証明書の作成

    openssl genrsa -out server.key 2048
    openssl req -out server.csr -key server.key -new
    openssl x509 -req -days 3650 -signkey server.key -in server.csr -out server.crt -extfile SAN.txt

    この一連のコマンドで、2048ビットの秘密鍵 server.key と、その秘密鍵に基づく証明書署名リクエスト(CSR) server.csr を作成します。最後に、CSRと秘密鍵から、有効期限3650日の自己署名証明書 server.crt を作成しています。この際、先ほど作成した SAN.txt ファイルを使ってSANを設定しています。

    HTTPSサーバーの起動

    http-server -S -C server.crt -K server.key -p 443

    最後に、http-server コマンドを実行して、HTTPSサーバーを起動します。このコマンドでは、作成した server.crtserver.key を指定し、ポート443でリッスンするように指定しています。

    hosts に以下の通り記載します

    127.0.0.1       sumito.jp

    これで、ローカル環境でHTTPSサーバーが立ち上がりました。ブラウザで https://sumito.jp/ にアクセスすると、自己署名証明書の警告が出る場合がありますが、それを無視して進めばウェブサーバーにアクセスできます。

    注意点として、この方法で作成した証明書は自己署名なので、実際の運用環境では使えません。

    本番環境で使う場合は、認証局から発行された適切な証明書を取得する必要があります

  • Shell でjsonの配列の変数から value を抜き出す

    Shell でjsonの配列の変数から value を抜き出す

    キーが固定の場合

    以下は、シェルスクリプトでJSONデータを読み込み、jqコマンドを使用して同様の処理を行う例です。

    #!/bin/bash
    
    json='[{"name":"Worker","no":"123"}, {"name":"User","no":"456"}, {"name":"Organization","no":"789"}, {"name": "Position","no":"123"}, {"name": "PositionTranslation","no":"123"}]'
    
    echo "$json" | jq -c '.[]' | while read -r item; do
      name=$(echo "$item" | jq -r '.name')
      no=$(echo "$item" | jq -r '.no')
      
      echo "$name"
      echo "$no"
      echo "-----"
    done

    このスクリプトでは:

    1. json変数にJSONデータを文字列として格納します。
    2. echo "$json" | jq -c '.[]'を使用して、JSONデータをパイプでjqコマンドに渡し、各オブジェクトを個別の行に分割します。
    3. while read -r itemを使用して、各オブジェクトを1つずつ読み込みます。
    4. echo "$item" | jq -r '.name'echo "$item" | jq -r '.no'を使用して、各オブジェクトからnamenoの値を抽出します。
    5. 抽出した値とセパレーターを表示します。

    結果はこちらです

    Worker
    123
    -----
    User
    456
    -----
    Organization
    789
    -----
    Position
    123
    -----
    PositionTranslation
    123
    -----
    
    

    キーが固定でない場合(接頭辞が共通の場合)

    JSONデータのキーが一部共通している場合、jqコマンドの to_entriesselectmapを組み合わせて目的の値を取得することができます。以下は、public_ip で始まるキーに対応する値を取得する例です。

    #!/bin/bash
    
    json='{"public_ip01": "1.2.3.4", "public_ip02": "2.3.4.5", "public_ip03": "12.2.3.4"}'
    
    echo "$json" | jq -r 'to_entries | map(select(.key | startswith("public_ip")).value)'
    

    このスクリプトでは:

    1. json 変数にJSONデータを文字列として格納します。
    2. echo "$json" | jq -r 'to_entries | map(select(.key | startswith("public_ip")).value)' を使用して、JSONデータを jq コマンドに渡し、以下の処理を行います:
      • to_entries で、JSONオブジェクトをキーと値のペアの配列に変換します。
      • map(select(.key | startswith("public_ip"))) で、キーが "public_ip" で始まるエントリーのみを選択します。
      • .value で、選択されたエントリーの値のみを取得します。
    3. jq の出力は、選択された値の配列になります。

    このスクリプトを実行すると、以下のような結果が得られます

    "1.2.3.4" "2.3.4.5" "12.2.3.4"

    これにより、public_ip で始まるキーに対応する値が取得できました。必要に応じて、この出力を変数に格納したり、ループ処理で個別に処理したりすることができます。

  • SendGridのSMTPサーバーを使ったメール送信をシェルスクリプトで確認する

    SendGridのSMTPサーバーを使ったメール送信をシェルスクリプトで確認する

    SendGridのSMTPサーバーを使ったメール送信をシェルスクリプトで確認する方法

    SendGridは、メールの配信を専門とするクラウドベースのサービスであり、多くの開発者やビジネスに利用されています。SendGridのSMTPサーバーを利用することで、アプリケーションからメールを送信することができます。ここでは、シェルスクリプトを使ってSendGridのSMTPサーバー経由でメールを送信する方法を紹介します。

    SendGridを使うメリット

    • 高い配信率: SendGridは、高い配信率を実現するために、メールの配信に関する様々な技術を駆使しています。
    • スパムフィルタリング: SendGridは、スパムメールの送信を防ぐために、高度なスパムフィルタリング技術を採用しています。
    • 分析とトラッキング: SendGridは、メールの開封率やクリック率などの詳細な分析データを提供し、メールマーケティングのパフォーマンスを追跡することができます。
    • シンプルなインテグレーション: SendGridは、SMTPリレーやWebAPIなど、様々なインテグレーション方法を提供しており、開発者にとって使いやすいサービスになっています。

    必要なもの

    • SendGridのアカウント
    • SendGridのAPIキー

    シェルスクリプト

    以下のシェルスクリプトを使って、SendGridのSMTPサーバー経由でメールを送信できます。

    #!/bin/bash
    
    smtp_server="smtp.sendgrid.net"
    smtp_port=587
    smtp_username="apikey"
    smtp_password="SG.xxxxxxxx"
    
    from_address="from@hoge.jp"
    to_address="to@hoge.jp"
    
    subject="Bash SMTP テスト"
    body="mail test"
    
    message="From: $from_address
    To: $to_address
    Subject: $subject
    
    $body"
    
    # メッセージをファイルに書き出す
    echo "$message" > message.txt
    
    # SMTPサーバーに接続してメールを送信
    curl --ssl-reqd \
    --url "${smtp_server}:${smtp_port}" \
    --user "${smtp_username}:${smtp_password}" \
    --mail-from "${from_address}" \
    --mail-rcpt "${to_address}" \
    --upload-file message.txt
    
    # 一時ファイルを削除
    rm message.txt
    

    手順

    1. SendGridのアカウントを作成し、APIキーを取得します。
    2. シェルスクリプトの smtp_password の部分を、取得したAPIキーに置き換えます。
    3. from_addressto_address を、実際の送信元と送信先のメールアドレスに置き換えます。
    4. シェルスクリプトを実行します。
     chmod +x script_name.sh ./script_name.sh
    1. メールが送信されたことを確認します。

    解説

    このシェルスクリプトでは、curlコマンドを使ってSendGridのSMTPサーバーに接続し、PLAINタイプの認証を使ってメールを送信します。

    メッセージ本文は一時ファイルに書き出され、curlコマンドの --upload-file オプションを使ってSMTPサーバーに送信されます。メール送信後、一時ファイルは削除されます。

    SendGridを使ったメール送信のテストの重要性

    SendGridを使ってメール送信機能を実装する前に、実際にメールが送信できることを確認することは非常に重要です。以下のような理由から、メール送信のテストを行うことが推奨されます。

    • メールの配信設定の確認: SendGridの設定が正しく行われているかどうかを確認することができます。
    • メールの内容の確認: メールの件名や本文が意図した通りに表示されるかどうかを確認することができます。
    • エラーの早期発見: メール送信に関する問題を早期に発見し、修正することができます。

    シェルスクリプトを使ったメール送信のテストは、手軽に実行できる方法の一つであり、SendGridを使ったメール送信機能の実装前に行うことをお勧めします。

    まとめ

    シェルスクリプトを使うことで、SendGridのSMTPサーバー経由でメールを送信できることを確認しました。この方法は、SendGridを使ってメール送信機能を実装する前の動作確認に役立ちます。メール送信のテストを行うことで、メールの配信設定やメールの内容を確認し、エラーを早期に発見することができます。SendGridを使ったメール送信機能の実装では、このようなテストを行うことが重要です。

    SendGridは、高い配信率やスパムフィルタリング、分析とトラッキング機能など、多くのメリットを提供するサービスです。SendGridを使うことで、信頼性の高いメール配信を実現することができます。

  • GitHub Actionsを使ったDockerイメージのビルドとAmazon ECRへのデプロイ

    GitHub Actionsを使ったDockerイメージのビルドとAmazon ECRへのデプロイ

    GitHub Actionsを使ったDockerイメージのビルドとAmazon ECRへのデプロイ

    今回は、GitHub Actionsを使ってDockerイメージをビルドし、Amazon Elastic Container Registry (ECR)にデプロイする方法について解説します。GitHub Actionsを活用することで、コードの変更に応じて自動的にDockerイメージをビルドし、ECRにプッシュすることができます。

    GitHub Actionsとは

    GitHub Actionsは、GitHubに組み込まれた継続的インテグレーション・継続的デプロイメント(CI/CD)のためのプラットフォームです。ワークフローを定義することで、コードのビルド、テスト、デプロイなどを自動化できます。GitHub Actionsでは、YAMLファイルを使ってワークフローを定義し、GitHubリポジトリ内の`.github/workflows`ディレクトリに配置します。

    Amazon ECRとは

    Amazon Elastic Container Registry (ECR)は、AWSが提供するフルマネージド型のDockerコンテナレジストリサービスです。ECRを使用すると、Dockerイメージを安全に保存、管理、デプロイすることができます。ECRは、AWSの他のサービスとの統合が容易で、スケーラビリティと可用性に優れています。

    ワークフローの解説

    それでは、GitHub Actionsを使ってDockerイメージをビルドし、Amazon ECRにプッシュするワークフローを解説していきます。

        - name: Login to Amazon ECR
          uses: aws-actions/amazon-ecr-login@v1
        - name: Build and push to Amazon ECR
          uses: docker/build-push-action@v3
            with:
            context: .
            push: true
            tags: ${{ env.ECR_REPOSITORY }}:${{ env.GITHUB_SHA }}
            cache-from: type=gha
            cache-to: type=gha,mode=max

    1. Amazon ECRへのログイン

    最初のステップでは、`aws-actions/amazon-ecr-login@v1`アクションを使用してAmazon ECRにログインします。このアクションは、AWSの認証情報を使用してECRレジストリにアクセスするために必要なログイン処理を行います。これは、以下の`aws`コマンドに相当します:

    aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <ecr-registry>

    2. DockerイメージのビルドとECRへのプッシュ

    次のステップでは、`docker/build-push-action@v3`アクションを使用して、Dockerイメージのビルドとプッシュを行います。このアクションは、以下の`docker`コマンドに相当します:

    docker build -t <ecr-registry>/<repository>:<tag> . docker push <ecr-registry>/<repository>:<tag>

    `with`セクションでアクションの設定を行います:

    • `context: .`: Dockerfileが存在するディレクトリを指定します。ここでは、現在のディレクトリ(`.`)を指定しています。
    • `push: true`: ビルドしたイメージをレジストリにプッシュすることを指定します。
    • `tags: ${{ env.ECR_REPOSITORY }}:${{ env.GITHUB_SHA }}`: イメージにタグを付けます。ここでは、環境変数`ECR_REPOSITORY`(ECRリポジトリのURL)とGitHubのコミットハッシュ(`GITHUB_SHA`)を組み合わせたタグを使用しています。
    • `cache-from: type=gha`: キャッシュからイメージレイヤーを読み込むことを指定します。`type=gha`は、GitHub Actionsのキャッシュを使用することを示します。
    • `cache-to: type=gha,mode=max`: ビルドしたイメージレイヤーをキャッシュに保存することを指定します。`mode=max`は、キャッシュを最大限に活用することを示します。

    キャッシュの活用

    GitHub Actionsでは、キャッシュ機能を利用してビルドの効率化を図ることができます。`cache-from`と`cache-to`オプションを使用することで、以前のビルドで作成されたイメージレイヤーをキャッシュから読み込み、ビルド時間を短縮できます。また、ビルドしたイメージレイヤーをキャッシュに保存することで、次回以降のビルドでそれらのレイヤーを再利用できます。

    キャッシュ機能は、`docker`コマンドや`aws`コマンドには直接対応する機能がありませんが、GitHub Actionsではこの機能を活用してビルドの効率化を図ることができます。

    まとめ

    GitHub Actionsを使ってDockerイメージをビルドし、Amazon ECRにデプロイする方法について解説しました。GitHub Actionsのワークフローでは、`aws-actions/amazon-ecr-login@v1`アクションを使用してECRにログインし、`docker/build-push-action@v3`アクションを使用してDockerイメージのビルドとプッシュを行います。また、キャッシュ機能を活用することで、ビルドの効率化を図ることができます。

    GitHub Actionsを活用することで、コードの変更に応じて自動的にDockerイメージをビルドし、ECRにデプロイすることができます。これにより、開発者はコードの開発に専念でき、CI/CDパイプラインの管理を簡素化できます。

    ぜひ、GitHub Actionsを使ってDockerイメージのビルドとデプロイを自動化してみてください。開発の効率化と品質向上に役立つはずです。

  • AWSコマンドでCloudFrontのキャッシュを消す

    AWSコマンドでCloudFrontのキャッシュを消す

    AWSコマンドでCloudFrontのキャッシュを消す方法

    AWSコマンドラインインターフェース(CLI)を使用してCloudFrontのキャッシュを無効化(Invalidation)する方法を説明します。

    手順

    以下のコマンドを実行します。

    aws cloudfront create-invalidation --distribution-id <distribution-id> --paths "<path1>" "<path2>" ...

    パラメータの説明

    • <distribution-id>: キャッシュを無効化したいCloudFrontディストリビューションのIDを指定します。
    • "<path1>" "<path2>" ...: キャッシュを無効化したいオブジェクトのパス(複数可)を指定します。パスはダブルクォーテーションで囲みます。

    ディストリビューションIDがEDFDVBD6EXAMPLEで、/index.html/images/logo.jpgのキャッシュを無効化したい場合は、以下のようになります。

    aws cloudfront create-invalidation --distribution-id EDFDVBD6EXAMPLE --paths "/index.html" "/images/logo.jpg"

    すべてのオブジェクトのキャッシュを無効化したい場合は、"/*"を指定します。

    aws cloudfront create-invalidation --distribution-id EDFDVBD6EXAMPLE --paths "/*"

    注意点

    • Invalidationリクエストには料金がかかります。
    • Invalidationが完了するまでには数分かかる場合があります。
    • 無効化されたオブジェクトは、次のリクエスト時に再びキャッシュされます。

    これにより、指定したパスのオブジェクトのキャッシュが無効化され、次のリクエスト時に新しいバージョンのオブジェクトがCloudFrontにキャッシュされます。

    以上で、AWSコマンドを使用してCloudFrontのキャッシュを消す方法の説明を終わります。ご不明な点があればお気軽にお問い合わせください。

  • Resource handler returned message: “The runtime parameter of nodejs14.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs20.x) while creating or updating functions.

    Resource handler returned message: “The runtime parameter of nodejs14.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs20.x) while creating or updating functions.

    AWS CDKでLambdaランタイムのアップグレードエラーを解決する

    AWS Cloud Development Kit (CDK)を使用してサーバーレスアプリケーションをデプロイする際に、Lambdaランタイムのバージョンアップによるエラーに遭遇することがあります。本記事では、そのようなエラーの原因と解決策について説明します。

    問題の概要

    CDKでLambda関数をデプロイしようとしたところ、以下のようなエラーが発生しました。

    Resource handler returned message: "The runtime parameter of nodejs14.x is no longer supported for creating or updating AWS Lambda functions. We recommend you use the new runtime (nodejs20.x) while creating or updating functions. (Service: Lambda, Status Code: 400, Request ID: 9xxx)" (RequestToken: e3c5cxxxx, HandlerErrorCode: InvalidRequest)
    

    このエラーは、AWS LambdaがNode.js 14.xランタイムのサポートを終了し、Node.js 20.xへの移行を推奨しているために発生しています。

    原因の特定

    エラーの原因を特定するために、プロジェクトの依存関係を確認したところ、package.jsonファイルに@aws-cdk/coreなどのCDK v1のパッケージが含まれていました。

    "dependencies": {
      "@aws-cdk/core": "^1.x.x",
      // ...
    }

    CDK v1はNode.js 14.xをデフォルトのランタイムとして使用していたため、これが原因でLambda関数のランタイムがNode.js 14.xになっていたのです。

    解決策

    この問題を解決するには、以下の手順を実行します。

    1. package.jsonファイルから、CDK v1の古いモジュール(@aws-cdk/coreなど)を削除します。
    2. CDK v2の新しいモジュール(aws-cdk-lib)をpackage.jsonファイルの依存関係に追加します。
    "dependencies": {
      "aws-cdk-lib": "^2.x.x",
      // ...
    }
    1. CDKのコード内で、@aws-cdk/coreなどの古いモジュールをインポートしている箇所を、aws-cdk-libからのインポートに変更します。
    2. npm installを実行して、更新された依存関係をインストールします。
    npm install
    1. CDKアプリケーションを再度合成し、CloudFormationテンプレートを生成します。
    cdk synth
    1. 生成されたCloudFormationテンプレートを確認し、Lambda関数のランタイムがNode.js 20.xに更新されていることを確認します。
    2. CDKアプリケーションをデプロイします。
    cdk deploy

    これで、Lambda関数のランタイムがNode.js 20.xに更新され、エラーが解消されるはずです。

    予防策

    今回の問題を予防するには、以下の点に注意が必要です。

    1. CDKのバージョンを最新のものに保つ
      • CDKは常に進化しており、新しいバージョンではモジュールの構造や名前が変更されることがあります。定期的にCDKのバージョンを更新することで、最新のベストプラクティスに沿ったアプリケーションを構築できます。
    2. 依存関係を定期的に確認する
      • プロジェクトの依存関係に古いモジュールが含まれていないか、定期的に確認することが重要です。古いモジュールを使用し続けると、セキュリティの問題や非互換性の問題が発生する可能性があります。
    3. AWS公式ドキュメントを参照する
      • AWSのサービスは常に進化しており、サポートされるランタイムやベストプラクティスも変化します。定期的にAWS公式ドキュメントを確認し、最新の情報を把握することが重要です。

    まとめ

    AWS CDKを使用する際に、古いCDKバージョンの依存関係が含まれていることが原因で、Lambdaランタイムのバージョンアップによるエラーに遭遇することがあります。このようなエラーは、古いモジュールを削除し、新しいモジュールを使用することで解決できます。また、CDKとAWSのサービスの進化に合わせて、定期的にアプリケーションの依存関係を見直すことが重要です。

    本記事が、同様の問題に直面した開発者の助けになれば幸いです。