プロキシ環境下のUbuntu16.04にdocker-machineでインストールする

# はじめに

最近は主に開発と検証目的でdockerを使用している。
[coreos](https://coreos.com/)と[docker-toolbox](https://www.docker.com/products/docker-toolbox)のバージョン違いで実行できないのがいい加減に辛くなってきたので、docker-machineでdockerホストを用意しようと思った。しかし、プロキシ環境だと結構引っかかる部分があったので、書いておく。
ちなみに手動で入れる場合のオフィシャルドキュメントは https://docs.docker.com/engine/installation/linux/ubuntulinux/ を参照

# docker-machineとは

[Docker Machine](https://docs.docker.com/machine/)とは、dockerホスティングサーバーの
プロビジョニング等を行うためのツール。
virtualboxやhyper-v等の仮想マシンシステムの他にも、awsやazure等のクラウドサービスにも対応している。
ただし、xenserverはオフィシャルではサポートしてない。

# 環境

* 開発、テスト用の仮想マシン群をLAN内Xenに展開しており、この環境にdockerホストマシンを作りたい。
* XenはLAN上にある
* docker-machineのドライバはxen対応でかつWindows用のものがない
* 指定されたプロキシを通らないとインターネットに出られない

今回はgeneric driverを使用することにする。

# generic driverの動き

generic driverは、以下の手順でdockerを対象マシンにインストールする

1. sshで対象マシンにログイン
2. curlでdockerが管理するaptリポジトリ情報を取得
3. apt-keyコマンドで、リポジトリの公開鍵をインポート
4. apt-getでdockerインストール
5. dockerのネットワーク設定(SSL)などを行う

以上からわかる通り、途中でネットワークに頻繁にアクセスしにいくので、プロキシ設定をしておかないと、どこかしらで失敗する。

# マシンの準備

docker-toolboxは、予めクライアントマシンに入っているものとする。

1. あらかじめ以下のサイトからubuntuのインストールisoをダウンロードしておき、CIFS等でXenからCDとして参照できるようにしておく。
    * [Get Ubuntu](http://www.ubuntu.com/download/)
2. ISOからマシンを起動し、SSHサーバーのみ入れる設定にして、インストールする。
3. VMの場合、スナップショットをとっておく(失敗時のやり直し用)
4. VM再起動後、SSHの公開鍵をsudoできるユーザーの~/.ssh/authorized_keysに追加する
5. **~/.sshの権限を0700、~/.ssh/authorized_keysの権限を0600にする**
    * この設定をしておかないと、sshがカギとして認識しない場合がある
6. `sudo visudo`コマンドで、以下の例のように編集する
    * `%sudo`から始まる行を`%sudo   ALL=(ALL:ALL) NOPASSWD:ALL`にする
    * `Defaults env_reset`以降の行に、以下の三つの行を追加する
        * `HTTP_PROXY=http://[プロキシサーバーのアドレス]:[ポート]`
        * `HTTPS_PROXY=http://[プロキシサーバーのアドレス]:[ポート]`
        * `NO_PROXY=[プロキシ除外リスト]`
7. `/etc/apt/apt.conf`内に、以下の設定を追加する
    * `Acquire::http::Proxy "http://172.16.1.71:8080";`
    * `Acquire::https::Proxy "http://172.16.1.71:8080";`
8. `~/.curlrc`に以下の行を追加する
    * `proxy=http://[プロキシサーバーのアドレス]:[ポート]`
    * curlは環境変数を無視するため
9. 以下のコマンドを実行して、docker公式の公開鍵を取得しておく
    * `sudo apt-key adv --keyserver-options HTTP_PROXY=http://[プロキシサーバーのアドレス]:[ポート] --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D`
    * 通常は`docker-machine create`のプロビジョニング中に取得するが、プロキシーを挟むと、どうも環境変数の値が無視されてしまうらしく、コマンドラインにオプションを追加しないと失敗した

なお、dockerのデータはすべて/var/lib/docker以下に保存されるため、予めこの下にパーティションを切っておけば、ルート領域を圧迫しなくてすむかもしれない。

# 対象マシンへのインストール

下記コマンドで、dockerを対象マシンにインストールする。

```
docker-machine create --driver generic \
  --engine-env HTTP_PROXY=http://[プロキシサーバーアドレス]:[ポート] \
  --engine-env HTTPS_PROXY=http://[プロキシサーバーアドレス]:[ポート] \
  --engine-env NO_PROXY=[プロキシ除外リスト] \
  --generic-ip-address=[対象マシンIP] \
  --generic-ssh-key=[SSH秘密鍵パス] \
  --generic-ssh-user=[SSHユーザー名] \
  [docker-machine内での識別名]
```

`--engine-env`の引数群が、プロキシ設定部分になる。ここを忘れると、
pullの時等に失敗するようになる。
ラベルは、docker-machineからアクセスするための識別名になる。

# docker-machineへのアクセス

## dockerコマンドでのアクセス

bash上で以下のコマンドを実行すると、必要な環境変数を自動的に設定してくれる
`eval $(docker-machine env [識別名])`
後は、普通に各種dockerコマンドを使用できる。

## ssh

以下のコマンドで、対象マシンにSSHログインできる。
`docker-machine ssh [識別名]`

# 最後に

身も蓋もない結論になるけど、最初からchefやらansibleやらの構成管理ツールを使えばよかったなぁと思ってる。各コマンドでプロキシ設定の参照先が微妙に違ってたので、正直しんどかった。

ただ、docker-machineを使うことの利点としては、SSLやswarm設定など、自分でやると面倒なことも一括でやってくれて、かつバージョンアップにも対応している等、便利な点もある。初期設定だけでなく、管理コマンドも提供してくれるし。

プロキシ設定やらsshやらを構成管理ツールに任せて、後はdocker-machineで管理するのがいいかもしれない。