背景・目的
Github ActionsでPythonのイメージをビルドするとき、別のprivate repositoryにある社内用ライブラリを持ってくる方法についてまとめました。
既に同僚の @elyunim26 の「GitHub Actionsでビルドするコンテナ内でGitHubのprivate repositoryをセキュアに参照する」という記事があったのですが、私はマシンユーザーではなくデプロイキーを利用していたため、安全にssh認証をする方法が必要でした。Build-time secretsを使うことでsshキーも安全にイメージのビルドに利用できます。
実装方法
簡単に説明すると、以下のような手順で実現できます。
- Github Actionsでsecretsからデプロイキー(秘密鍵)を読み込む
- DockerのBuildkitの機能を使ってセキュアに受け渡す
- 通常通り
pip install
を行う
デプロイキーの設定
まず、ライブラリ側のリポジトリにデプロイキーを設定する必要があります。デプロイキーの設定方法はGithubの公式ドキュメントを参照してください。
Github Actionsの設定
次のような要素に気をつける必要があります。トラブルシューティングには(Pythonとnode.jsという違いはありますが)GitHub Actions で private repository の node module をインストールするが役に立ちました。
-
GITHUB
で始まるsecretsは禁止されている - secretsでは改行が使えないため、事前に改行を
\n
などに置換した形で登録して、sed
で置換するなどの回避方法が必要
以下は設定例です。我々のチームではAWSを利用しているため、後半にECRにpushするコードも含まれています。
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: ${{ steps.extract_repository.outputs.repository }}
IMAGE_TAG: ${{ github.sha }}
DEPLOY_KEY_GITHUB: ${{ secrets.DEPLOY_KEY_GITHUB }}
run: |
echo ${DEPLOY_KEY_GITHUB} > .deploy_key
sed -i -e "s#\\\\n#\n#g" .deploy_key
chmod 600 .deploy_key
DOCKER_BUILDKIT=1 docker build --secret id=ssh,src=.deploy_key \
-t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG \
-t $ECR_REGISTRY/$ECR_REPOSITORY:latest \
.
rm .deploy_key
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
Dockerfileの設定
我々のチームではpoetryを使うことが多いのでpyproject.toml
を利用していますが、requirements.txt
を使う場合でも同様の設定でいけるはずです。
# syntax=docker/dockerfile:experimental
FROM python:3.7
# ssh-keyscanの実行のため、元にするイメージによってはopenssh-clientのインストールが必要
RUN apt-get install -y openssh-client git
COPY ./pyproject.toml /app/pyproject.toml
COPY ./src /app/src
WORKDIR /app
RUN mkdir -m 700 $HOME/.ssh
RUN ssh-keyscan -H github.com > $HOME/.ssh/known_hosts
RUN --mount=type=secret,id=ssh,dst=$HOME/.ssh/id_rsa \
pip install --upgrade pip && \
pip install . && rm pyproject.toml
pyproject.toml
では次のように記述されています。これはpoetryの公式ドキュメントにもある通り、poetry add
コマンドでリポジトリを指定することで作成されるものです。
[tool.poetry.dependencies]
{ライブラリ名} = {git = "ssh://git@github.com/{ユーザー名}/{ライブラリ名}.git", rev = "main"}