PrivateなPythonパッケージがあるけどGitHub Actions上でpipenvインストールしてDocker Imageをビルドしたい


# はじめに

GitHub上のプライベートレポジトリにあるPythonパッケージを使っているPythonプロジェクトにて、GitHub Actions上でDocker Imageをビルドするまでの知見を共有。

# バージョン・環境

* Docker Image: python:3.8.2-slim

# やり方

## `Pipfile.lock`を確認

[pipenv](https://pipenv-ja.readthedocs.io/ja/translate-ja/)を利用します。

`Pipfile.lock`は下記のようにプライベートレポジトリをインストールする設定であることを確認します。

```py:Pipfile.lockの一部
        "private-repository-package": {
            "editable": true,
            "git": "https://github.com/username/private-repository-package.git",
            "ref": "812u4dd76db6298ce50b5569a9a1d80759ba6e80"
        },
```

今回は[netrc](https://linuxjm.osdn.jp/html/netkit/man5/netrc.5.html)を利用してインストールするので、httpsでインストールします。
`ref=コミットハッシュ`とすることで、指定したいバージョンをインストールすることができます。

まだインストールしていない場合は、`pipenv install private-repository-package` のようにローカルでインストールし、refを修正して再度`pipenv install`すると更新されます。

詳細は公式ドキュメントを見ると良いでしょう。[pipenv公式ドキュメント](https://pipenv-ja.readthedocs.io/ja/translate-ja/basics.html)

## `Dockerfile`

Dockerfileの内容です。

イメージには-slimなものを利用しています。-slimでないイメージと比較すると1/3ほどイメージの容量を小さくすることができます。

```Dockerfile:Dockerfile
FROM python:3.8.2-slim

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
    ca-certificates \
    git \
    && apt-get clean && \
    rm -rf /var/lib/apt/lists/*

ENV WORKDIR /app/
WORKDIR ${WORKDIR}
COPY Pipfile Pipfile.lock ${WORKDIR}

# setup .netrc to install dependencies in private GitHub repository
ARG PRIVATE_REPO_ACCESS_KEY
RUN echo "machine github.com" > /root/.netrc && \
    echo "login $PRIVATE_REPO_ACCESS_KEY" >> /root/.netrc && \
    echo "passowrd x-oauth-basic" >> /root/.netrc && \
    chmod 600 /root/.netrc

# install Python dependencies
RUN pip install pipenv --no-cache-dir && \
    pipenv install --system --deploy && \
    pip uninstall -y pipenv virtualenv-clone virtualenv

# remove anythings security and uncessary
RUN rm /root/.netrc && \
    rm Pipfile Pipfile.lock

COPY src/ $WORKDIR

CMD python ./run.py
```

ポイントは[netrc](https://linuxjm.osdn.jp/html/netkit/man5/netrc.5.html)を利用している点です。`PRIVATE_REPO_ACCESS_KEY`という引数を外(今回はGitHub Actions)から受け取り、それを`/root/.netrc`ファイルへ渡して、GitHub上のプライベートレポジトリへhttpsアクセスできるようにしています。

そして、この`.netrc`ファイルを利用し、pipenv installが完了したその後、

```
# remove anythings security and uncessary
RUN rm /root/.netrc && \
    rm Pipfile Pipfile.lock
```

この処理を入れることで、Docker Imageには`PRIVATE_REPO_ACCESS_KEY`の値を消去し残さないようにします。

## GitHub Actions

### GitHubパーソナルトークンを取得しSecretに設定

GitHub上でプライベートレポジトリへアクセスするためのパーソナルトークンを取得します。
やり方は[こちらの公式ドキュメント](https://help.github.com/ja/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line)がわかりやすいです。

そして得られたパーソナルトークンを対象のGitHubレポジトリのSettingからSecretに登録します。
このやり方も他記事に図付きで乗ってあります。公式ドキュメントは[こちら](https://help.github.com/ja/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets)です。

### GitHub Actions Yaml

上記で設定したパーソナルトークンをシークレットから取得しそれを先程のDockerfileでの`PRIVATE_REPO_ACCESS_KEY`としてdockerコマンドに渡してImageビルド処理をします。

```yaml:GitHubActionsワークフローYamlの一部
      env:
        PRIVATE_REPO_ACCESS_KEY: ${{ secrets.PRIVATE_REPO_ACCESS_KEY }}
      run: |
        docker build --build-arg PRIVATE_REPO_ACCESS_KEY=${PRIVATE_REPO_ACCESS_KEY} .
```

# 参考

* https://qiita.com/terukizm/items/2da698db98cba61d0e4d
* https://help.github.com/ja/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line