開発環境用のDockerでprivate repositoryにあるgemやnpmパッケージをインストールする

## TL;DR

GitHub向けの独自の認証情報キャッシュを用意する。

```sh:git-credential-github-token
#!/bin/sh

echo protocol=https
echo host=github.com
echo username=$GITHUB_USERNAME
echo password=$GITHUB_TOKEN
```

Dockerfileに以下のような内容を追記し、gitでcloneする際https経由でcloneするようにし、httpsの認証に独自の認証情報キャッシュを使うよう設定する。

```Dockerfile:Dockerfile
FROM ruby

WORKDIR /app

COPY ./git-credential-github-token /usr/local/bin
RUN git config --global url."https://github.com/YOUR_ORG_NAME/".insteadOf ssh://git@github.com/YOUR_ORG_NAME/ \
  && git config --global credential.helper github-token
```

GitHubでrepo権限を持ったPersonal Access Tokenを発行する。
https://github.com/settings/tokens

以下のように環境変数でユーザー名とPersonal Access Tokenを渡して実行。

```
$ docker build .
$ docker run -it -e GITHUB_USERNAME=YOUR_USER_NAME -e GITHUB_TOKEN=YOUR_GITHUB_TOKEN -v .:/app IMAGE bash
```

`bundle install`/`npm install`する

## GitHubのprivate repositoryをcloneする際sshではなくhttpsを使う

例えば`Gemfile`に以下のように`git`オプションが指定されていることがあります。

```rb
gem :your_gem_name, git: 'ssh://git@github.com/YOUR_ORG_NAME/your_gem_name.git'
```

sshを使うとGitHubで使っている鍵をDockerコンテナーに渡さないと`bundle install`出来ません。
鍵にパスフレーズがかかっていると`bundle install`時にパスフレーズ入力が必要になり不便です。

回避するために色々やりかたがあります。

- sshをつかわない
- パスフレーズがない鍵をGitHubに登録して使う
- docker containerを立ててそこに`ssh -A`して開発
- ssh-agentのコンテナを立てておきそこから情報をもらう e.g. https://github.com/nardeas/docker-ssh-agent

ここではsshをつかわない方向で進めていきます。
sshをつかわない方法はいくつかあります。

- gitの設定を上書きして常に`https`を使うようにする
- Gemfileの`git`オプションを書き換える

デプロイの都合などでなるべく`Gemfile`を変更したくない場合、gitの設定を上書きして常に`https`を使うようにするのがお手軽です。

Dockerfileに以下のコマンドを追加します。

```
$ git config --global url."https://github.com/YOUR_ORG_NAME/".insteadOf ssh://git@github.com/YOUR_ORG_NAME/
```

このコマンドを実行すると以下のような設定ファイルが作成されます。

```~/.gitconfig
[url "https://github.com/YOUR_ORG_NAME/"]
        insteadOf = ssh://git@github.com/YOUR_ORG_NAME/
```

この設定を行うとGitHubのYOUR_ORG_NAME以下のプライベートなリポジトリをcloneする際に、常にhttpsが使われるようになります。

## git config --global credential.helper github-token

privateリポジトリをcloneする場合、GitHubではユーザーの認証が必要です。
privateなgemファイルやnpmパッケージをインストールする際に以下のようなプロンプトが出ます。

```
Username for 'https://github.com': 
```

手入力は面倒です。入力する手間を省くため独自の認証情報キャッシュを使って認証の手間を省きます。

参考: [Git - 認証情報の保存](https://git-scm.com/book/ja/v2/Git-%E3%81%AE%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E3%83%84%E3%83%BC%E3%83%AB-%E8%AA%8D%E8%A8%BC%E6%83%85%E5%A0%B1%E3%81%AE%E4%BF%9D%E5%AD%98)

今回は以下のような認証情報キャッシュを作成します。
環境変数の`GITHUB_USERNAME`/`GITHUB_TOKEN`を用いて認証を行います。

```sh:git-credential-github-token
#!/bin/sh

echo protocol=https
echo host=github.com
echo username=$GITHUB_USERNAME
echo password=$GITHUB_TOKEN
```

パスが通っているところに`git-credential-github-token`を置いて、以下のようなコマンドを叩いて`~/.gitconfig`に設定を追加します。

```
$ git config --global credential.helper github-token
```

```~/.gitconfig
[credential]
        helper = github-token
```

## GitHubの認証に使うトークンを発行する

GitHubでrepo権限を持ったPersonal Access Tokenを発行します。
https://github.com/settings/tokens


## 環境変数経由でGitHubの認証情報を渡す

独自の認証情報キャッシュで使っている環境変数に自身のユーザー名と先程作成したPersonal Access Token設定してコンテナーを起動します。

```
$ docker run -it -e GITHUB_USERNAME=YOUR_USER_NAME -e GITHUB_TOKEN=YOUR_GITHUB_TOKEN -v .:/app IMAGE bash
root@04d6eff95b41:/app# bundle install
```

ユーザー名やトークンがhistoryやrcに残るのが嫌なので、僕は`envchain`を使って環境変数を設定しています。
https://github.com/sorah/envchain

```
$ envchain --set myapp GITHUB_USERNAME GITHUB_TOKEN
$ envchain myapp docker run -it -e GITHUB_USERNAME=$GITHUB_USERNAME -e GITHUB_TOKEN=$GITHUB_TOKEN -v .:/app IMAGE bash
```

## 実際の`docker-compose.yml`の例

こういう感じです。

```docker-compose.yml
version: '3'

services:
  web:
    build: .
    command: sh -c 'bundle check && bundle exec rails s -b 0.0.0.0'
    environment:
      GITHUB_USERNAME: $GITHUB_USERNAME
      GITHUB_TOKEN: $GITHUB_TOKEN
    volumes:
      - .:/app
      - gem-data:/usr/local/bundle
      - npm-data:/app/node_modules

volumes:
  gem-data:
  npm-data:
```

`up`する前に以下のような感じで`bundle install`/`npm install`してます。

```
$ envchain myapp docker-compose build
$ envchain myapp docker-compose run --rm web bash
root@04d6eff95b41:/app# bundle install
```