GitHub Actions CI パイプライン実践:ゼロから自動化ビルド・テストを構築
午前3時、携帯が震える。同僚からのメッセージ:「本番環境がダウンした。昨日マージしたコードに問題がある。」
頭が真っ白になった。ローカルでテストは通ったはずだ。ログを確認してわかったのは、ローカルの Node バージョンが 20、テスト環境は 18 で、ある API の挙動が異なっていたこと。その瞬間、罵りたい気持ちになった。マージ前に CI パイプラインで自動テストを走らせていれば、こんなことは起きなかっただろう。
正直に言うと、手動でテストを走らせるなんて、10人の開発者のうち9人は忘れる。残りの1人が忘れないのは、おそらく痛い目を見たことがあるからだ。GitHub Actions はこの問題を解決してくれる。コードをプッシュした後、自動的にビルド、テスト、デプロイを実行。自分で気にする必要はなく、マシンが処理してくれる。
この記事では、ゼロから完全な CI パイプラインを構築する方法を紹介する。そのままコピーして使えるワークフローテンプレート、Matrix 戦略による複数バージョン並列テスト(ビルド時間を半分以上削減)、そして筆者が経験したハマりどころと実践的なノウハウを含む。準備はいいか?始めよう。
第一章:GitHub Actions クイックスタート
GitHub Actions とは
簡単に言えば、GitHub Actions は GitHub に組み込まれた自動化プラットフォームだ。ローカルでコードをプッシュすると、クラウド上でテスト、ビルド、デプロイを実行してくれる。完全自動化だ。
以前は CI/CD を構築するには、Jenkins サーバーを自分で立て、設定、メンテナンス、アップグレードと、すべて自分でやる必要があった。GitHub Actions の優れている点は、サーバーを管理する必要がなく、ソフトウェアをインストールする必要もなく、リポジトリに YAML ファイルを置くだけで済むことだ。さらに、毎月 2000 分が無料で提供される(パブリックリポジトリは無制限)。個人プロジェクトや小規模チームには十分だ。
Jenkins や Travis CI と比較すると、GitHub Actions の利点は明確だ。GitHub リポジトリと深く統合されており、PR 内でビルドステータスを直接確認できる。設定が簡単で、Groovy 構文を学ぶ必要がない。エコシステムも豊富で、公式 Marketplace に数千の既製 Action が用意されている。欠点もある。GitHub にロックインされ、GitLab に移行するには設定を書き直す必要がある。複雑なエンタープライズ向けパイプラインでは、Jenkins の方が柔軟かもしれない。しかし、ほとんどのプロジェクトでは GitHub Actions で十分だ。
コア概念の概要
GitHub Actions を学び始めると、いくつかの概念に混乱しがちだ。簡単に説明しよう。
Workflow(ワークフロー):YAML ファイル1つで、自動化プロセス全体を定義する。「main ブランチにプッシュするたびにテストを実行」というのがワークフローだ。.github/workflows/ ディレクトリに配置する。
Job(ジョブ):ワークフロー内のステップのグループ。複数の Job は並列実行できるし、依存関係を設定できる。例えば、「テスト」Job を実行してから「デプロイ」Job を実行する。
Step(ステップ):Job 内の具体的な操作。順番に実行される。コマンドの実行(npm test)や、他人が書いた Action の呼び出し(actions/checkout@v4)がある。
Runner(ランナー):Job を実行する仮想マシン。GitHub は3種類を提供:ubuntu-latest(Linux)、windows-latest(Windows)、macos-latest(macOS)。自分のサーバーを使うこともできるが、ほとんどの場合、公式のランナーで十分だ。
例えるなら、Workflow は脚本、Job は脚本の複数のシーン、Step は各シーンの具体的な動作、Runner はそのシーンを演じる俳優だ。
最初の CI ワークフロー
考えすぎず、まずは動かしてみよう。プロジェクトのルートディレクトリに .github/workflows/ci.yml を作成し、以下のコードを貼り付ける。
name: CI Pipeline # ワークフロー名、GitHub Actions ページに表示
on:
push:
branches: [main] # main ブランチにプッシュした時にトリガー
pull_request:
branches: [main] # main ブランチへの PR 時にトリガー
permissions:
contents: read # 最小権限の原則:読み取り権限のみ
jobs:
build:
runs-on: ubuntu-latest # 最新の Ubuntu 環境を使用
timeout-minutes: 15 # タイムアウト時間、ハングアップ防止
steps:
- name: Checkout code
uses: actions/checkout@v4 # コードをチェックアウト
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20 # Node.js 20 を使用
cache: 'npm' # npm キャッシュを有効化
- name: Install dependencies
run: npm ci # 依存関係をインストール、ci は install より高速で信頼性が高い
- name: Run tests
run: npm test # テストを実行
- name: Build
run: npm run build # ビルド
このコードは何をしているのか?
最初の部分 on はトリガー条件を定義。main ブランチへのプッシュ、または main ブランチへの PR 時にトリガーする。2番目の部分 permissions は権限を宣言。最小権限の原則に従い、contents: read のみを付与し、ワークフローが誤ってリポジトリを変更するのを防ぐ。3番目の部分がコア。build という Job が Ubuntu 上で、コードのチェックアウト、Node のセットアップ、依存関係のインストール、テストの実行、ビルドを順番に実行する。
このコードをコミットして GitHub にプッシュし、リポジトリの Actions ページを開く。緑の円が回っているのが見えるはずだ。Runner がワークフローを実行している。数分待って、すべてが緑のチェックマークになれば、おめでとう。最初の CI パイプラインが成功した。
赤いバツが表示されたら?ログを開いて確認しよう。各ステップの出力が明確に表示される。90% のケースは依存関係のインストール失敗かテスト自体の問題で、CI 設定とは関係ない。
第二章:CI パイプラインの核心設定
第一章のワークフローは動作するが、実用的なレベルにはまだ距離がある。この章では4つのコア設定について説明する。トリガー、権限管理、環境変数、依存関係キャッシュだ。これらが CI パイプラインの骨格であり、適切に設定すれば、ワークフローはより安全で効率的になる。
トリガー:いつ実行するか
トリガーはワークフローがいつ起動するかを決定する。最もよく使われる2つは push と pull_request だ。
on:
push:
branches: [main, dev] # main または dev ブランチへのプッシュでトリガー
paths:
- 'src/**' # src ディレクトリ内のファイルが変更された時のみトリガー
- 'package.json' # package.json の変更もトリガー(依存関係の更新)
pull_request:
branches: [main] # main ブランチへの PR 時にトリガー
paths フィルターは特に実用的だ。例えばプロジェクトに docs/ ディレクトリがある場合、ドキュメントの変更で CI を走らせるべきではない。paths を設定すれば、コードの変更時のみビルドが実行され、リソースも時間も節約できる。
push と PR 以外にも、いくつかのトリガー方法がある。
schedule:cron 式を使ったスケジュール実行。例えば毎日午前にビルドを実行する。
on:
schedule:
- cron: '0 0 * * *' # 毎日 UTC 0時(日本時間8時)
あるプロジェクトでこれを使って定期依存関係チェックを行っている。毎日 npm outdated を実行し、期限切れのパッケージを検出し、メールで通知する。
workflow_dispatch:手動トリガー。コードをプッシュせずにビルドを実行したい場合(特定の設定をテストするなど)、これが役立つ。Actions ページに “Run workflow” ボタンが表示され、クリックするだけで手動実行できる。
on:
workflow_dispatch: # 手動トリガー、追加設定不要
権限管理:セキュリティ最優先
GitHub Actions はデフォルトでワークフローに GITHUB_TOKEN を付与する。このトークンはリポジトリの読み書き、PR の作成、さらにコードのプッシュまでできる。便利に聞こえるが、リスクも意味する。ワークフローが悪用されると、攻撃者がリポジトリの書き込み権限を取得できる可能性がある。
2021年にセキュリティインシデントが発生した。あるオープンソースプロジェクトの CI ワークフローが悪用され、攻撃者が偽の PR で悪意あるコードを送信した。教訓は痛ましいものだった。現在、GitHub は「明示的に最小権限を宣言する」という原則を推奨している。
permissions:
contents: read # リポジトリの内容のみ読み取り可能、書き込み不可
pull-requests: write # PR を作成する必要がある場合、個別に宣言
純粋な CI パイプライン(テストとビルドのみ)では、contents: read で十分だ。ワークフローが Release を公開したり、PR にコメントしたりする場合は、必要に応じて権限を追加する。
実用的なテクニック:リポジトリ設定でデフォルトの権限を “Read repository contents permission” に変更する。これにより、すべてのワークフローはデフォルトで読み取り権限のみを持ち、書き込みが必要な場合は個別に宣言する。もう一つの防御線で、リスクが減る。
環境変数:階層的な管理
環境変数には3つのレベルがある。workflow レベル、job レベル、step レベルだ。レベルが低いほどスコープは狭くなるが、上位の値を上書きできる。
env:
NODE_ENV: production # workflow レベル、すべての job で使用可能
CI: true # 多くのツールはこの変数を検出して動作を調整
jobs:
build:
env:
BUILD_TARGET: web # job レベル、build job 内でのみ有効
steps:
- name: Run custom script
env:
MY_VAR: hello # step レベル、このステップ内でのみ有効
run: echo $MY_VAR
なぜ階層化するのか?例えば、プロジェクトに build と deploy の2つの Job がある。NODE_ENV は両方の Job で必要なので、workflow レベルに配置。しかし BUILD_TARGET は build Job でのみ使用するため、job レベルに配置する方が明確だ。あるステップで一時的な変数が必要な場合(例えばスクリプトのパラメータ)、step レベルに配置する。
機密情報はどう扱うか?絶対に YAML に直接書いてはいけない。GitHub は Secrets 機能を提供している。リポジトリ設定でシークレットを追加し(例:API_KEY)、ワークフロー内で ${{ secrets.API_KEY }} で参照する。Secrets はログ内で自動的にマスクされ、漏洩しない。
steps:
- name: Deploy to server
env:
SSH_KEY: ${{ secrets.SSH_KEY }} # Secrets から参照
run: |
echo "$SSH_KEY" > private.key
ssh -i private.key user@server 'deploy.sh'
依存関係キャッシュ:ビルドの高速化
プロジェクトの依存関係が多い場合(数百の npm パッケージ)、CI で毎回最初からインストールすると時間がかかる。あるプロジェクトでは、依存関係のインストールに3分、テストの実行に1分かかり、インストールが75%の時間を占めていた。
GitHub Actions はキャッシュメカニズムを提供しており、インストール済みの依存関係を保存し、次回は直接使用できる。最も簡単な方法は setup-node に組み込まれたキャッシュ機能だ。
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm' # npm 依存関係を自動キャッシュ
cache: 'npm' を1行追加するだけで、最初の実行では通常通りインストールし、同時に node_modules をキャッシュに保存する。2回目以降、package-lock.json が変更されていなければ、キャッシュから直接取得し、インストール時間は3分から10秒に短縮される。
pnpm や yarn を使用する場合は、cache: 'pnpm' または cache: 'yarn' に変更する。
より詳細なキャッシュ制御には actions/cache を使用できる。
- name: Cache dependencies
uses: actions/cache@v4
with:
path: ~/.npm # npm グローバルキャッシュディレクトリ
key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
key はキャッシュの一意識別子だ。ここでは package-lock.json のハッシュ値を使用している。ロックファイルが変更されるとキャッシュは無効になり、再インストールされる。restore-keys はバックアップ戦略で、完全一致が見つからない場合、同種のキャッシュから一部を復元する。
キャッシュヒット率が高ければ、ビルド速度は大幅に向上する。あるプロジェクトでの実測値:キャッシュなしで4分、キャッシュありで1.5分。毎日20回ビルドを実行すれば、節約された時間でブログ記事が1本書ける。
第三章:Matrix 戦略:並列テスト
これは GitHub Actions で最も気に入っている機能で、この記事の主要なセールスポイントだ。Matrix 戦略は1つの Job を複数の並列実行される Job に変換し、異なるバージョン、異なるオペレーティングシステムを同時にテストできる。1回のプッシュで、数秒以内に十数個のビルドタスクが起動し、すべて並列実行される。総時間は直列実行より半分以上短くなる。
Matrix とは
例えば、プロジェクトが Node 16、18、20 の3つのバージョンで正常に動作するかテストしたいとする。従来の方法は3つの Job を書くか、1つの Job 内で順番にバージョンを切り替えてテストする。こうすると、設定が重複するか、時間がかかる。
Matrix はテーブルのようなものだ。横軸が Node バージョン、縦軸がオペレーティングシステムで、各セルが独立したテストタスクだ。GitHub Actions はすべての組み合わせを自動生成し、並列実行する。
strategy:
matrix:
node: [16, 18, 20]
os: [ubuntu-latest, windows-latest]
この設定は6つの Job を生成する。Node 16 on Ubuntu、Node 16 on Windows、Node 18 on Ubuntu… という具合に。完了までの総時間は、最も遅い Job に依存し、すべての Job の合計ではない。
バージョンマトリックス:複数 Node バージョンテスト
あるプロジェクトでこの問題に遭遇した。開発には Node 20 を使用していたが、ある日、Node 18 では動作しないというユーザーからの報告があった。調査した結果、ある API が Node 18 では異なる動作をすることがわかった。早めに複数バージョンテストを行っていれば、このバグは本番に出なかったはずだ。
Matrix で複数バージョンテストを行うのは簡単だ。
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false # あるバージョンが失敗しても、他のバージョンは継続
matrix:
node-version: [16, 18, 20, 22] # この4つのバージョンをテスト
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }} # matrix 内のバージョンを動的に使用
cache: 'npm'
- run: npm ci
- run: npm test
主なポイントを説明する。
matrix.node-versionでテストするバージョンのリストを定義${{ matrix.node-version }}で steps 内で参照、各 Job は異なる値を受け取るfail-fast: falseは、あるバージョンが失敗しても他のバージョンの実行を中断しない。デフォルトはtrueで、1つ失敗するとすべて停止する。互換性テストでは無効にすることをお勧めする。そうすれば、すべてのバージョンのテスト結果を確認できる。
include と exclude:ある組み合わせが不要だったり、追加の設定が必要な場合、この2つのキーワードが使える。
strategy:
matrix:
node-version: [16, 18, 20]
os: [ubuntu-latest, windows-latest]
exclude:
- node-version: 16 # Node 16 + Windows の組み合わせはテストしない
os: windows-latest
include:
- node-version: 20 # Node 20 を macOS でも追加で実行
os: macos-latest
exclude は不要な組み合わせを除外し、include は追加の組み合わせを追加する。テスト範囲を柔軟に制御できる。
OS マトリックス:クロスプラットフォームテスト
プロジェクトが異なるオペレーティングシステムで実行される可能性がある場合(コマンドラインツールなど)、OS マトリックスが役立つ。
jobs:
test:
runs-on: ${{ matrix.os }} # OS を動的に指定
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
ここで注意すべき点がいくつかある。
プラットフォームの違い:Windows と Linux ではファイルパスが異なる(\ vs /)。一部のコマンドラインツールの動作も異なる。クロスプラットフォームテストは、これらの問題を事前に発見するのに役立つ。
コスト管理:GitHub Actions の課金は OS ごとに異なる。Linux は月2000分無料、Windows は Linux の2倍、macOS は10倍の消費量だ。macOS Runner を使用すると、毎月の無料枠がすぐになくなる。
節約戦略:
- macOS テストは必要な場合のみ(プロジェクトが実際に macOS で使用される場合)
- macOS テストを別のワークフローに分け、
workflow_dispatchで手動トリガー - パブリックリポジトリは無制限、プロジェクトを公開できる場合は公開を推奨
パフォーマンス改善のテクニック
Matrix は並列実行できるが、無限ではない。GitHub はデフォルトで並列数を制限し、リソースの枯渇を防ぐ。手動で制御できる。
strategy:
max-parallel: 4 # 最大4つの Job を同時実行
matrix:
node-version: [16, 18, 20, 22]
Matrix の組み合わせが多い場合(10+ Job)、max-parallel を設定すれば、一度に多くの Job が実行されるのを防ぎ、無料枠の消費を抑えられる。
キャッシュヒットで高速化:Matrix 内の各 Job は独自のキャッシュを持つ。setup-node の cache は自動的に処理するため、追加設定は不要。主なポイントは、package-lock.json と node-version が安定している場合、キャッシュヒット率が高いことだ。
不要なステップを減らす:Matrix 内の各 Job ですべてのステップを実行するが、実は不要な場合がある。例えば、コードチェック(lint)は通常、複数バージョンテストを必要としない。
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run lint # lint は Node 20 で1回のみ実行
test:
needs: lint # lint 成功後に test を実行
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test
これで lint は1回のみ、test は3つのバージョンで実行される。効率が向上する。
実測データ:あるプロジェクトで、Matrix なしでは3つのバージョンを順番にテストするのに12分かかった。Matrix で並列実行すると、総時間は4分(最も遅いバージョンに依存)。8分節約でき、毎日10回ビルドを実行すれば、1ヶ月で節約した時間で映画を1本見られる。
第四章:実践経験とトラブルシューティング
最初の3章で CI パイプラインの設定方法を説明した。この章では「クイックリファレンス」をまとめた。セキュリティ、パフォーマンス、トラブルシューティングの3つの観点から。問題が発生したらここを確認すれば、時間を節約できる。
セキュリティ実践リスト
| 実践 | 説明 | 例 |
|---|---|---|
| permissions を明示的に宣言 | デフォルト権限に依存せず、必要な権限を明確に宣言 | permissions: { contents: read } |
| Secrets で機密情報を管理 | API Key、SSH 鍵などをハードコードしない | ${{ secrets.API_KEY }} |
| トリガーブランチを制限 | すべてのブランチで CI を走らせず、必要なブランチのみ | branches: [main] |
| SHA で Action を参照 | バージョンタグではなく具体的な commit SHA を使用し、改ざんを防止 | actions/checkout@b4ffde65f46336ab88eb53be808477a39b6bc2b1 |
| timeout を設定 | ハングアップで無料枠を消費しないように | timeout-minutes: 15 |
最後の項目は多くの人が見落としている。Action のバージョン参照。公式 Action は通常 @v4 のようなタグを使用し、アップグレードが簡単だ。しかし、タグは変更可能だ。理論上、誰かが @v4 を悪意あるコードに向けることができる。SHA で参照(@b4ffde65f...)すると、アップグレードは面倒だが、より安全だ。本番環境のプロジェクトでは、SHA の使用をお勧めする。
パフォーマンス改善リスト
| テクニック | 効果 | 設定方法 |
|---|---|---|
| 依存関係キャッシュを有効化 | インストール時間を 50% 以上短縮 | cache: 'npm' |
| npm install ではなく npm ci を使用 | インストールが高速で信頼性が高い | run: npm ci |
| timeout-minutes を設定 | ハングアップで無料枠を消費しないように | timeout-minutes: 15 |
| Matrix で並列実行 | 総時間を 60% 以上短縮 | strategy.matrix |
| concurrency で重複ビルドをキャンセル | 同じブランチで最新のみ実行 | concurrency.group: ${{ github.ref }} |
concurrency は実用的だ。同じブランチに連続して5回プッシュすると、デフォルトでは5つのビルドが実行される。concurrency を設定すれば、最初の4つはキャンセルされ、最後の1つのみ実行される。
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # 実行中の古いビルドをキャンセル
よくある問題のクイックリファレンス
| エラーメッセージ | 原因 | 解決策 |
|---|---|---|
Permission denied | 権限不足 | permissions 設定を確認し、必要な権限を追加 |
Cache not found | キャッシュキーが一致しない | cache key を確認、package-lock.json が変更されていないか |
npm ERR! network | ネットワークタイムアウト | タイムアウト時間を増やすか、国内ミラーを使用 |
Out of memory | Node メモリ不足 | NODE_OPTIONS=--max_old_space_size=4096 を設定 |
EACCES permission denied | ファイル権限の問題 | スクリプトの先頭に chmod +x script.sh を追加 |
Error: Cannot find module | 依存関係がインストールされていない | npm ci が正常に実行されたか確認、エラーログをチェック |
よくあるシナリオの対処法。
ネットワークタイムアウト:GitHub Runner が npm レジストリに接続するのが遅い場合がある。.npmrc でミラーを設定できる。
- name: Configure npm registry
run: echo "registry=https://registry.npmmirror.com" > .npmrc
メモリ不足:大規模プロジェクトのビルドで Node がメモリを使い果たす場合がある。環境変数を追加する。
env:
NODE_OPTIONS: --max_old_space_size=4096 # Node に 4GB メモリを割り当て
キャッシュが有効にならない:最初の実行でキャッシュがないのは正常だ。package-lock.json が存在することを確認(npm ci にはロックファイルが必要)。また、setup-node の cache パラメータがパッケージマネージャーと一致しているか確認(npm/pnpm/yarn)。
結論
長々と説明したが、核心はシンプルだ。YAML ファイル1つで CI パイプラインを構築できる。権限宣言は最小限の原則に従う。環境変数は3層で管理。依存関係キャッシュでインストール時間を半分に短縮。Matrix 戦略で複数バージョンの並列テストが簡単になる。
この記事の第1章のワークフローテンプレートをコピーして、Node バージョンとプロジェクトのコマンドを変更すれば、プロジェクトに CI を追加できる。まずは動かしてから、徐々に調整しよう。Matrix 戦略を試してみることをお勧めする。たとえ2つの Node バージョンをテストするだけでも、並列テストの効率性を実感できるはずだ。複数の緑のチェックマークが同時に表示される感覚は、なかなか爽快だ。
GitHub Actions を使用していて問題に遭遇したら、コメント欄で質問してほしい。よくある問題を第4章のクイックリファレンスに追加し、より多くの人がハマりどころを避けられるようにする。
GitHub Actions CI パイプラインを構築
ゼロから完全な CI パイプラインを構築し、自動化ビルドとテストを実現
⏱️ 目安時間: 30 分
- 1
ステップ1: ワークフローディレクトリを作成
プロジェクトのルートディレクトリに `.github/workflows/` ディレクトリを作成し、すべてのワークフロー設定ファイルを格納する。 - 2
ステップ2: 基本 CI 設定を作成
`ci.yml` ファイルを作成し、トリガー条件(push/PR)、権限(最小限の原則)、Job ステップ(checkout、setup-node、install、test、build)を設定する。 - 3
ステップ3: 依存関係キャッシュを有効化
`setup-node` ステップに `cache: 'npm'` パラメータを追加し、npm 依存関係を自動キャッシュして、後続のビルドを高速化する。 - 4
ステップ4: Matrix で複数バージョンテストを設定
`strategy.matrix` 設定を追加し、テストする Node バージョンのリスト(例:[16, 18, 20])を指定して、並列テストを実現する。 - 5
ステップ5: コミットしてビルド結果を確認
設定ファイルをコミットし、GitHub にプッシュして、Actions ページでビルドステータスとログを確認する。
FAQ
GitHub Actions の無料枠は毎月どれくらい?
CI ワークフローはどのブランチでトリガーすべき?
なぜ npm install ではなく npm ci を推奨するのか?
Matrix 戦略でビルド時間はどれくらい短縮できる?
キャッシュが有効にならないことがあるのはなぜ?
CI で機密情報(API Key、SSH 鍵)をどう扱う?
8 min read · 公開日: 2026年4月6日 · 更新日: 2026年4月20日
関連記事
Nginx SSL/TLS 設定実践:HTTPS証明書から A+ セキュリティ強化まで
Nginx SSL/TLS 設定実践:HTTPS証明書から A+ セキュリティ強化まで
Docker マルチステージビルド実践:本番イメージを 1GB から 10MB にスリム化
Docker マルチステージビルド実践:本番イメージを 1GB から 10MB にスリム化
Supabase Edge Functions 実践ガイド:Deno ランタイムと TypeScript 開発入門

コメント
GitHubアカウントでログインしてコメントできます