GitHub Actionsを使ってGitHub PackagesでNode.jsのDockerイメージを管理する
2021年7月13日
0 分で読めます現在、オープンソース開発に取り組んでいる方の多くは、GitHubコミュニティで活動し、オープンソースプロジェクトやそのリポジトリに参加していることでしょう。GitHubエコシステムに最近加わったのがGitHub Packagesです。2019年に発表され、現在はGitHub Packagesのコンテナレジストリが一般提供されるなど、さらにアップデートが進んでいます。これにより、Dockerベースのイメージや、OCI準拠のその他の形式をGitHubエコシステム内だけで公開したりプルしたりできるようになりました。
この記事では、GitHub Actionsのワークフローを一つずつ解説します。Node.jsプロジェクトをDockerイメージとして公開し、GitHub Packagesのコンテナレジストリにプッシュする方法を紹介します。
始める前に、GitHubユーザー向けの専用サポートフォーラム、GitHub Support Communityをご存じですか?困ったことがあれば、ぜひチェックしてみてください。
この記事で取り上げるNode.jsプロジェクトはdocklyです。Dockerコンテナやサービスを管理するための、臨場感のあるターミナルインターフェースを提供するオープンソースのNode.jsコマンドラインツールです。

GitHub Actionsワークフローを作成する
GitHubでオープンソースリポジトリを開き、Actionsタブ、続いてNew Workflow、set up a workflow yourselfの順にクリックします。次のような画面が表示されます。

まず、ワークフローファイル名を定義します。docker-publish.yml、またはお好みの命名規則に従った名前を設定してください。
GitHubによってワークフローのコードがあらかじめ入力されている場合があります。その場合はすべて削除し、次のコードを貼り付けてください。
上記のワークフローでは、次の規則を設定しています。
このワークフローは、mainブランチへのコミット、またはmainブランチ宛てのプルリクエストでのみ実行されます。注:以前の規則に従ってリポジトリでmasterブランチを使用している場合は、ここおよびコードスニペット全体でブランチ名を変更してください。また、
<v*.*.*>というsemver形式のタグがリポジトリにプッシュされたときにも実行されます。これにより、バージョンごとにDockerイメージを公開できます。新しいDockerイメージが公開されると、GitHubリポジトリのタグも作成されるようにします。
以降のワークフロージョブで使うグローバル環境変数を設定し、GitHub Container Registry(ghcr.io)を指定します。また、Dockerイメージ名には、Docker Hubで使われている標準的な形式
<user>/<repo>を適用します。たとえばlirantal/nodejs-appのようになります。
次にジョブを定義し、Dockerイメージのビルドから公開までのプロセスを設定します。
GitHub ActionsワークフローでDockerイメージをビルドする
DockerイメージをGitHub Packagesのコンテナレジストリ(またはGitHub自体)に公開するには、まず有効なアカウントで認証する必要があります。そのため、ビルドおよび公開ジョブの最初のステップでログインします。
次のコードをコピーし、先ほどのコードに続けて貼り付けてください。
ここで定義したジョブで実行される処理を確認しましょう。
最初のステップでは、リポジトリのソースコードをチェックアウトします。
続いて、GitHub Packagesのコンテナレジストリに認証します。先ほど定義した環境変数
REGISTRYを再利用し、GitHub独自のコンテナイメージレジストリであるghcr.ioを指定しています。認証に使うユーザー名はワークフローを開始したユーザーのもので、リポジトリの所有者であるあなたのユーザー名と一致するはずです。パスワードには
GITHUB_TOKENを使用します。これはGitHub Actionsのワークフローで自動的に利用できるため、リポジトリにシークレットや環境変数として手動で追加する必要はありません。また、プルリクエストの場合はレジストリへのログインが行われません。これは不要なうえ、プルリクエストのCIやフォークで機密情報が漏えいするおそれがあるためです。上記のコードスニペットの最後のステップでは、イメージからメタデータを抽出し、Dockerイメージのビルドプロセスで利用できるようにします(次がこのワークフローの最後のステップです)。メタデータには、Dockerのビルドアクションで利用できるタグやラベルの情報が含まれます。具体的には、入力値
imagesで、タグのベース名として使用するDockerイメージを指定します。
DockerイメージをビルドしてGitHub Packagesのコンテナレジストリに公開する
最後のステップでは、Dockerイメージをビルドして公開します。これらの処理に対応するアクションを使い、1つのステップとして実行します。ただし、ワークフローのpush入力には条件を設定し、プルリクエストでイベントが発生した場合はイメージをレジストリに公開しないようにしています。
これで完了です。
インデントを正しく設定してワークフローを保存し、mainブランチにマージして実行すると、イメージがビルドされ、GitHub Packagesのコンテナレジストリに公開されます。
すべてうまくいけば、私の場合のように、ジョブが成功したことを示す待望の緑色のチェックマークが表示されます。

DockerイメージをGitHub Packagesのコンテナレジストリにプッシュするには?
GitHub Actionsのワークフローファイルで、公式Docker GitHub Actionのdocker/build-push-actionを使用し、環境変数REGISTRYにghcr.ioを設定してください。
GitHub PackagesのコンテナレジストリからDockerイメージをプルする
プロジェクトのDockerイメージが公開レジストリに公開されたので、ローカルの開発環境からプルして試してみましょう。
プルするDockerイメージのバージョンを指定するには?
docker pullコマンドには、<registry>/<user>/<repo>:<image tag>という形式の引数を追加します。たとえば、GitHub Packagesのコンテナレジストリにあるmy-nodejs-app imageの「latest」タグをプルするには、次のコマンドを使います。docker pull ghcr.io/lirantal/my-nodejs-app
やった、成功です!
でも、ちょっと待ってください。GitHub PackagesにプッシュしたDockerイメージを、もっと簡単に確認する方法はないでしょうか?こちらをご覧ください。
GitHub PackagesでDockerイメージを見つける
GitHubプロフィールページ(私の場合はhttps://github.com/lirantal?tab=packages)を開くと、公開中のDockerイメージをすべて確認できます。
このチュートリアルに沿ってDockerイメージをビルドした方は、自分のイメージを見つけられるでしょうか?こちらが、リポジトリのGitHub Actions CIを使ってGitHub PackagesにプッシュしたDockerイメージパッケージのページです。

公開したDockerイメージにlatestタグがない場合
使用中のmainまたはmasterブランチのDockerイメージを、タグを指定せず名前だけでプルしようとして、よく使われるDockerイメージタグlatestがないことに気づいたかもしれません。これは、semver(セマンティックバージョニング)タグがプッシュされていない場合に発生します。自分のリポジトリでタグをプッシュしていれば、利用できる可能性があります。
公開するDockerイメージにlatestエイリアスを必ず設定するには、次のようにメタデータアクションを更新します(複数行のflavorキーが追加されている点に注目してください)。
ただし、この設定では、mainブランチをトリガーとしてCIジョブが実行されるたびに、公開するDockerイメージのエイリアスとしてlatestタグが必ず設定されます。
Dockerイメージにlatestタグを付けるには?
ビルド済みのイメージにローカルでタグを付けるには、次のDocker tagコマンドの形式を使用します。docker tag <local image name> <new tag>。たとえば、docker tag my-nodejs-app lirantal/my-nodejs-app:latestです。
タグを指定してDockerイメージを実行するには?
特定のDockerイメージタグを指定してイメージを実行するには、完全修飾イメージ名とタグをdocker runコマンドに指定します。たとえば、docker run --rm -p 27017:27017 mongo:latestです。
GitHub Actions MarketplaceにあるDockerやコンテナ関連の便利なインテグレーション
GitHub Actionsワークフローを見つけて作成するもう一つの方法は、GitHub Actions Marketplaceを利用することです。コード品質、依存関係管理、セキュリティなど、9,000以上のワークフローが揃っています。オープンソースライブラリに潜むサードパーティの脆弱性からプロジェクトを守り、チームがセキュアコーディングのプラクティスに従っていることを確認できるSnyk GitHub Actionsもあります。
この記事では、Dockerイメージをビルド、テストし、レジストリに公開する方法を取り上げています。Marketplaceを探し回るよりも簡単に始める方法があります。リポジトリにDockerfileがあれば、GitHubが自動的に検出し、GitHub Actionsで使える関連ワークフローを提案してくれます。Actionsタブを開くだけです。

最初に提案されるワークフローPublish Docker Containerを使えば、先ほど確認したものと同様のDockerイメージのビルド・公開ワークフローを設定できます。
まとめと次のステップ
セキュアな開発プラクティスに興味が湧いてきましたか?すばらしいですね!学習を始めて、チームからセキュリティの評価を得るのに役立つ資料をいくつか紹介します。
サプライチェーンセキュリティは重要です。GitHubのセキュリティに関するベストプラクティス10選を確認し、同じ過ちを繰り返さないようにしましょう。
Node.jsやnpmパッケージの開発に興味がありますか?私もです!GitHub Actionsを使ってnpmパッケージを安全に公開する方法を紹介する記事を書きました。
GitHubエコシステムをよく利用する方は、ワークフローとより緊密に統合できるSnykのコードスキャンもぜひご覧ください。GitHub Security Code Scanning:オープンソースの依存関係を保護する
キャプチャー・ザ・フラッグを始めよう
オンデマンドのバーチャル入門ワークショップを視聴して、キャプチャー・ザ・フラッグの課題の解き方を学びましょう。
