Packerを使うとDockerfileを使わずにChefやPuppetからDockerのイメージを作成することができる(詳しくは"Packerを使ってChef/Puppet/AnsibleでDockerのイメージをつくる"に書いた).ChefとかPuppetのような資産が既にある場合は,それを使うのも良い(インフラCIでベースDockerイメージだけChefで作ってしまってみたいなことも考えているが,まだ試し中).
イメージができたら,次はそのイメージをどこかにホストする必要がある.また業務で利用するなら認証機構のちゃんとしたプライベートレジストリを使いたい.Dockerのイメージの保存先の選択肢は,今のところ以下の3つがある.
- docker/docker-registryを運用する
- DockerHubを利用する
- Quay.ioを利用する
まず、自分でdocker-registryを運用するのはしんどいのでやめた方が良い.次にDockerHubは,Dockerが提供しているRegistryで,プライベートレポジトリを作成することもできる.Quay.ioはCoreOSが買収したDockerのプライベートRegistryサービス.
DockerHubとQuay.ioの違いを簡単に書くと,DockerHubは安く(プライベートレポジトリ1つは無料で使える),大抵の機能は使えるが,たまにpending地獄になってビルドが遅いとかが発生したりする.Quay.ioはまあまあ値段はする(DockerHubの倍くらい)が,Dockerhubと同等の機能がありながら,1つのレポジトリに複数のユーザを追加したり,GitのブランチでAutomated Buildを指定したり,Squashイメージを提供したり,ダッシュボードでイメージの差分を確認したり,などなど面白い機能が多い.
Packerはイメージ作成後にそれをレジストにpushする機能を持っている.インターネットを見渡した限り,その方法を書いている記事は見当たらなかったので,簡単に書いておく.今回はquay.ioを例に使う.
PackerとDocker
まず,簡単にPackerとDockerについて.PackerがDockerイメージの作成でやってくれるのは以下
- ベースとなるDockerイメージのpull(builder)
- Dockerイメージのprovision(provisioner)
- Docekrイメージのタグつけ,レジストリへのpush(post-processor)
"Packerを使ってChef/Puppet/AnsibleでDockerのイメージをつくる"に書いたので今回は詳しく書かないが,Packerが面白いのは,provisionerで,ChefやAnsible,Puppetどれでも適用できること.いろんなマシンイメージを同じように扱えること.
今回は,builderやpost-processerでレジストリ(Quay.io)とやりとりするための設定方法について書く.なおQuay.io以外でも同じようにできる.
machine.json
例えば,公式のDockerHubからベースとなるubuntuイメージを取得して(認証は必要ない),完成したイメージをQuay.ioにpushする(認証が必要)ためのmachine.json
は以下のようになる.
{
"builders":[
{
"type": "docker",
"image": "ubuntu:latest",
"commit": true
}
],
"post-processors": [
[
{
"type": "docker-tag",
"repository": "quay.io/tcnksm/base",
"tag": "latest"
},
{
"type": "docker-push",
"login": true,
"login_server": "quay.io",
"login_username": "YOUR_NAME",
"login_password": "YOUR_PASSWORD",
"login_email": "YOUR_EMAIL"
}
]
]
}
post-processorでprovisionの終わったDockerイメージをどうするかを定義する.docker-tag
でレポジトリの名前をつけてcommitし、docker-push
で実際にイメージをレジストリにpushする.
Quay.ioを使う場合は、レポジトリの名前は,quoy.io/<username>/<reponame>
とする.push先の認証設定はdocker-push
においてlogin_server
, registry_username
, login_password
, login_email
を全て書けばよい.
ベースのDockerイメージをプライベートレポジトリからpullしたいときは,同じ項目をbuildersに書けばよい.
Packerの設定ファイルでの認証情報の扱い
設定ファイルに認証情報を直接書くべきではない.実行時に切り替えられるとよい.Packerでは以下の2つの方法が使える.
- 環境変数を使う
- 別ファイルに切り出す
環境変数を使う
環境変数を使うにはmachine.jsonを以下のように書き換える.
{
"variables":{
"registry_username": "{{ env `REGISTRY_USERNAME`}}",
"registry_password": "{{ env `REGISTRY_PASSWORD`}}",
"registry_email": "{{ env `REGISTRY_EMAIL`}}"
},
"builders":[
{
"type": "docker",
"image": "ubuntu:12.04",
"commit": true
}
],
"post-processors": [
[
{
"type": "docker-tag",
"repository": "quay.io/tcnksm/base",
"tag": "latest"
},
{
"type": "docker-push",
"login": true,
"login_server": "quay.io",
"login_username": "{{user `registry_username`}}",
"login_password": "{{user `registry_password`}}",
"login_email": "{{user `registry_email`}}"
}
]
]
}
まず,variablesという項目を追加し,そこに参照したい変数と初期値を定義する.ここに定義した値は他の設定項目からテンプレートとして"{{user VALUE}}"
という形で参照できるようになる.そしてvariablesに与える値を"{{env ENV_VALUE}}"
とすれば,環境変数でその値を設定できるようになる.
実行は以下のようにすればよい.
$ REGISTRY_USERNAME=<YOUR_NAME> \
REGISTRY_PASSWORD=<YOUR_PASS> \
REGISTRY_EMAIL=<YOUR_EMAIL> \
packer build machine.json
"{{env ENV_VALUE}}"
を書けるのがvariablesセクションに限定されているのはとても良い.値がどうやって設定されるか混乱しないし,入力ソースも一箇所なので追跡もしやすい.
別ファイルに切り出す
実行時に毎回環境変数を設定するのは面倒くさい.認証情報をファイルに切り出して(もちろんレポジトリにはpushしない),それを使う方法もある.以下のように-var-file
というオプションを使う.
$ cat variables.json
{
"registry_username": "YOUR_NAME",
"registry_password": "YOUR_PASS",
"registry_email": "YOUR_EMAIL"
}
$ packer build -var-file=variables.json machines.json
まとめ
Packerを使ってDockerのイメージを作成し、それをプライベートレポジトリにpushする方法について書いた.また、Packerで認証情報を安全に取り扱う方法についても書いた.