目的
GitHub上にRパッケージのソースリポジトリがあり、rocker/rstudio にこのRパッケージをインストールしたDockerイメージを作成する場面を考えます。このとき、ビルド中にGitHubと接続するため認証情報を使用する必要があります。
過去の記事 "Dockerイメージビルド時の秘密情報の扱い方に関するまとめ" で述べたように、ビルド時に秘密情報を使用する際はビルド後のイメージに残らないよう慎重に取り扱う必要があります。
別の記事 "rockerにGitHub上のRパッケージをインストールしたイメージの安全なビルド方法" では、認証情報として Personal Access Token を BuildKit や マルチステージビルド で取り扱う方法を紹介しました。ローカルマシン上でビルドを実行する場合は基本的に BuildKit を利用するのが良いでしょう。
本記事ではローカル環境ではなくGCPの Cloud Build でビルドパイプラインを構築することを考えます。
認証には Personal Access Token ではなくSSH秘密鍵を使用します。
この秘密鍵はビルド対象のコンテナには渡さず、docker build
の前に GitHub からソースをダウンロードするようにします。
これは前の記事 "Cloud Build で シークレット マネージャー を使用して GitHub プライベートリポジトリに接続する" で紹介した方法の応用例になります。
概要
適当なGCPプロジェクト projectname
とRパッケージソースのGitHubリポジトリ username/pkgname
、およびビルド構成管理用のGitHubリポジトリ username/imagename
を用意します。
GitHub と Cloud Build および Container Registry (GCR) を組み合わせて、次のような流れのビルドパイプラインを構築します:
- ビルド構成管理リポジトリ
username/imagename
へプッシュされると Cloud Build の自動トリガーが実行される - rocker/rstudio にRパッケージ
username/pkgname
をインストールしたイメージがビルドされる - ビルドされたイメージがコンテナレジストリ
gcr.io/projectname
にプッシュされる
認証に使用するSSH秘密鍵については次のように扱います:
- ビルド後のイメージに秘密鍵が残らないよう、
docker build
では秘密鍵を直接扱わないようにします。そのため、Dockerfile
内でremotes::install_github
やinstallGithub.r
などは使用せず、Rパッケージはソースからインストールします。 - Rパッケージのソースは
docker build
を行う前のステップでGitHubからダウンロードします。 - Cloud Buildへの秘密鍵の受け渡しには シークレット マネージャー を利用します。
基本的な構成は前の記事 "Cloud Build で シークレット マネージャー を使用して GitHub プライベートリポジトリに接続する" と同一です。Cloud Buildやシークレット マネージャーの使用方法についてはそちらでより詳しく説明しています。
GCPのプロジェクト設定
このプロジェクト projectname
では Cloud Build、シークレット マネージャー、Container Registryを有効化しておきます。
ローカルマシンに gcloud
コマンドラインツールをインストールしておきます。
次のコマンドで gcloud
の認証を実行します:
gcloud auth login
対象プロジェクトを projectname
に設定します:
gcloud config set project projectname
Docker CLIでGCRに接続するため、認証ヘルパーの設定を行っておきます(参考):
gcloud auth configure-docker
GitHubマシンユーザー
GitHub リポジトリ username/pkgname
にSSH鍵認証で接続するための準備を行います。
デプロイキーを使う方法もありますが、ここでは マシンユーザー を利用します(デプロイキーは同一の鍵を複数のリポジトリで使用できないため、この方法で複数のRパッケージをインストールしたい場合には不便です)。 マシンユーザーとは、GitHubを自動処理で利用するためのユーザーアカウントです。
マシンユーザーは通常のGitHubユーザーアカウントと同じように作成します。
ここではマシンユーザーの名前を machine-user-name
とします。
このユーザー用のSSH公開鍵 github_machine_user_key.pub
と秘密鍵 github_machine_user_key
のペアを生成します:
ssh-keygen -f github_machine_user_key
GitHubの設定ページ を開き、github_machine_user_key.pub
をマシンユーザーの公開鍵として登録します。
またソースリポジトリ username/pkgname
側ではユーザー machine-user-name
を Collaborator に招待するなどしてアクセスを許可します。
シークレット マネージャー
次のようにしてGitHubマシンユーザーのSSH秘密鍵 github_machine_user_key
をシークレット マネージャーに保存します:
gcloud secrets create github_machine_user_key --data-file=github_machine_user_key
この秘密鍵に Cloud Build からアクセスできるようにするため、
Cloud IAM
でサービスアカウント [PROJECT_NUMBER]@cloudbuild.gserviceaccount.com
に対して Secret Manager のシークレット アクセサー の役割を与えます。ここで [PROJECT_NUMBER]
はプロジェクト projectname
のプロジェクト番号です。
ビルド構成管理リポジトリ username/imagename
このリポジトリでは cloudbuild.yaml
と Dockerfile
、および known_hosts
の3つのファイルを作成します。そして次のような内容のビルド構成を記述します:
- シークレットマネージャーからGitHubマシンユーザーのSSH秘密鍵を取得する(ステップ1)
- マシンユーザーとしてGitHubにSSHで接続し、Rパッケージのソースをクローンする(ステップ2)
- docker build でRパッケージをソースからインストールする(ステップ3)
- ビルドされたDockerイメージはGCRに保存する(成果物)
cloudbuild.yaml
これが主となるビルド構成設定ファイルです。 以下のような内容で保存します:
steps:
# シークレット マネージャからSSH秘密鍵をダウンロードする
- name: gcr.io/cloud-builders/gcloud
entrypoint: bash
args:
- -c
- gcloud secrets versions access --secret=github_machine_user_key latest > /root/.ssh/id_rsa
volumes:
- name: ssh
path: /root/.ssh
# GitHubとのSSH接続のセットアップを行う
- name: gcr.io/cloud-builders/git
entrypoint: bash
args:
- -c
- |
chmod 600 /root/.ssh/id_rsa
cat <<EOF >/root/.ssh/config
Hostname github.com
IdentityFile /root/.ssh/id_rsa
EOF
cat <<EOF >/root/.gitconfig
[user]
name = machine-user-name
email = [email protected]
EOF
mv known_hosts /root/.ssh/known_hosts
volumes:
- name: ssh
path: /root/.ssh
# GitHubからRパッケージのソースをダウンロードする
- name: gcr.io/cloud-builders/git
args: ['clone', '--depth', '1', '[email protected]:username/pkgname', '/src/pkgname']
volumes:
- name: ssh
path: /root/.ssh
- name: src
path: /src
# docker build を実行する
- name: gcr.io/cloud-builders/docker
args: ['build', '-t', 'gcr.io/projectname/imagename:tag', '.']
volumes:
- name: src
path: /src
# ビルドされたイメージをGCRに保存する
images: ['gcr.io/projectname/imagename:tag']
Dockerfile
こちらは以下のような内容とします:
FROM rocker/rstudio:3.6.3
COPY /src /src
RUN install2.r -r NULL -- /src/pkgname && rm -rf /src
known_hosts
このファイルは github.com を既知のSSHホストとして確認するために使用されます。 次のコマンドで生成します:
ssh-keyscan -t rsa github.com > known_hosts
以上のファイルを作成したらコミットしてGitHubリポジトリ username/imagename
にプッシュします。
ビルドトリガーの設定
GCPコンソールの "ビルドトリガー" ページ を開き、次のような設定でビルドトリガーを作成します:
- GitHubリポジトリ
username/imagename
を Cloud Source Repositories にミラーリングしてビルドソースとする - master ブランチへのプッシュなど適当なトリガー条件を設定
- ビルド構成ファイルとして
cloudbuild.yaml
を使用する
テスト
リポジトリ username/imagename
に適当なコミットを push するか、手動でトリガーを実行するとビルドが開始されます。
ビルドの状態やログは "ビルド履歴" のページ から確認することができます。
ビルドが完了しGCRにDockerイメージ gcr.io/username/imagename:tag
が保存されれば成功です。
このイメージをローカルに pull して rocker/rstudio と同じように起動すれば、RStduio Serverに接続してパッケージがインストール済みになっていることを確認できます。
# GCRからイメージを pull する
docker pull gcr.io/username/imagename:tag
# コンテナを起動する
docker run -d --rm -p 8787:8787 -e PASSWORD=password -e DISABLE_AUTH=true gcr.io/username/imagename:tag
# http://localhost:8787 から RStudio Server に接続する
まとめ
- Google Cloud Build で rocker/rstudio をベースとした Docker イメージを作成するビルドパイプラインを構築しました。
- このビルドの中でGitHub上のRパッケージをインストールするようにしました。
- 前の記事 のように、シークレット マネージャー から認証用のSSH秘密鍵を取得してGitHubに接続し、Rパッケージのソースをダウンロードするような構成としました。
docker build
の中ではremotes::install_github
などを使わず、ダウンロード済みのソースからRパッケージをインストールするので、認証情報がビルドされたイメージ内に残ってしまう心配はありません。
関連記事
- "Dockerイメージビルド時の秘密情報の扱い方に関するまとめ"
- "rockerにGitHub上のRパッケージをインストールしたイメージの安全なビルド方法"
- "Cloud Build で シークレット マネージャー を使用して GitHub プライベートリポジトリに接続する"