プライベートなnpmパッケージをDockerfileでインストールしてGitHub Actionsでビルドする
はじめに
こんにちは。
医療系スタートアップUbie株式会社の「Ubie Discovery」というチームで働く@jimboです。Webフロントエンドが得意なソフトウェアエンジニアです。
社内限定のプライベートなnpmパッケージを開発し、npm registryやGitHub Packagesに登録して、さまざまなプロジェクトでnpm installして利用したいことがあります。
(UbieにもGitHub Packagesで管理するプライベートなnpmパッケージが存在しています。)
パブリックなパッケージと違い、プライベートなパッケージをnpm installするためには、npm registryあるいはGitHub Packagesへのアクセストークンが必要です。個人(ローカル)で利用する場合は、アクセストークンを記載した ~/.npmrc
ファイルを用意すればOKです。
# npm registory を利用している場合
//registry.npmjs.org/:_authToken=YOUR_ACCESS_TOKEN
# GitHub Packages を利用している場合
//npm.pkg.github.com/:_authToken=YOUR_ACCESS_TOKEN
しかし、Dockerfile内でnpm installをしている場合は、 ~/.npmrc
を参照できないためうまくいきません。別の方法でDockerにアクセストークンを参照させる必要があり、かつGitHub ActionsでDockerをビルドするには、いくつかの工夫が必要です。
今回はその方法について調べたので、まとめてみます。
Dockerfileでプライベートなパッケージをnpm installする
次のようなDockerfileでは、npm install時に認証エラーとなってしまいます。
FROM node:alpine
COPY package*.json ./
RUN npm install
...
$ docker image build .
=> ...
=> [1/3] FROM docker.io/library/node:alpine@sha256:f372a9ffcec27159dc9623bad29997a1b61eafbb145dbf4f7a64568be2f59b99 0.0s
=> CACHED [2/3] COPY package*.json ./ 0.0s
=> ERROR [3/3] RUN npm install 2.3s
------
> [3/3] RUN npm install:
#6 2.211 npm ERR! code E401
#6 2.213 npm ERR! Incorrect or missing password.
#6 2.213 npm ERR! If you were trying to login, change your password, create an
#6 2.213 npm ERR! authentication token or enable two-factor authentication then
#6 2.213 npm ERR! that means you likely typed your password in incorrectly.
#6 2.213 npm ERR! Please try again, or recover your password at:
#6 2.213 npm ERR! https://www.npmjs.com/forgot
#6 2.213 npm ERR!
#6 2.213 npm ERR! If you were doing some other operation then your saved credentials are
#6 2.213 npm ERR! probably out of date. To correct this please try logging in again with:
#6 2.214 npm ERR! npm login
#6 2.222
#6 2.222 npm ERR! A complete log of this run can be found in:
#6 2.222 npm ERR! /root/.npm/_logs/2021-06-10T12_58_35_383Z-debug.log
これはDockerでnpm installする際に、Dockerにアクセストークンが渡されていないのが原因です。
.npmrc
ファイルを用意する
プロジェクト専用のまず、~/.npmrc
とは別に、プロジェクト専用の .npmrc
ファイルをプロジェクトのルートディレクトリ(package.json
と同じ場所)に用意します。
ファイルの中身は次のようにします。(GitHub Packagesを利用した例です)
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
.npmrc
を参照できるようにする
Dockerfileで次に、用意した .npmrc
ファイルをDockerfile内でコピーして、 npm install時に参照されるようにします。
FROM node:alpine
COPY .npmrc .npmrc
COPY package*.json ./
RUN npm install
ただし、まだ環境変数 NPM_TOKEN
がDockerfile内で定義されていないため、このままではやはりエラーとなります。
環境変数をDockerfileに渡す
Docker内で環境変数を参照するにはどうすればよいでしょう。
次のようにDockerfile内で環境変数をセットするのは可能ですが、Dockerfileにアクセストークンを直接書くのは管理上避けるべきです。
FROM node:alpine
ENV NPM_TOKEN xxxxxxxxxxxxxxx
COPY .npmrc .npmrc
COPY package*.json ./
RUN npm install
そこで利用できるのが、ARG パラメータ です。(Docker 1.9から利用可能です)
ARGパラメータを使うと、Dockerの外側からDocker内部に環境変数を渡すことができます。
次のようにDockerfileを変更します。
FROM node:alpine
ARG NPM_TOKEN
COPY .npmrc .npmrc
COPY package*.json ./
RUN npm install
これで環境変数 NPM_TOKEN
を受け取ることができます。
最後に、dockerビルド時に --build-arg
オプションを使って環境変数を指定します。これでDockerの外側からDocker内部に環境変数を渡すことができるようになりました。
$ export NPM_TOKEN=xxxxxxxxx
$ docker build --build-arg NPM_TOKEN=${NPM_TOKEN} .
GitHub ActionsでDockerビルドする
ローカル環境であれば、上記のように環境変数 NPM_TOKEN
にトークンをセットすればよいのですが、GitHub Actionsで docker build
を実行する場合はどうすればよいでしょう。
次のように GitHub Actionsのワークフローファイル内で環境変数を設定することもできますが、YAMLファイルに直接トークンを書くのはやはり避けたいところです。
jobs:
build:
runs-on: ubuntu-latest
env:
NPM_TOKEN: xxxxxxxxxx
steps:
- name: Build Image
run: |
docker image build --build-arg NPM_TOKEN=${{ env.NPM_TOKEN }} .
GitHubのシークレットを使うと、安全に管理されたアクセストークンを利用できます。
Organization やリポジトリ 単位でシークレットを作成できますが、社内でプライベートなnpmパッケージを用意している場合は、Organizationでシークレットを作成しておくと、さまざまなリポジトリで利用しやすくなります。
作成したシークレットは、GitHub Actionsのワークフローファイルでは ${{ secrets.xxxxxxx }}
で参照できます。例えば、ACCESS_TOKEN_GITHUB_PACKAGE_REGISTRY
という名前でシークレットを用意した場合は、次のようになります。
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build Image
run: |
docker image build --build-arg NPM_TOKEN=${{ secrets.ACCESS_TOKEN_GITHUB_PACKAGE_REGISTRY }} .
これで、privateなnpmパッケージをDockerfileでインストールしてGitHub Actionsでビルドできるようになりました。
Discussion