1. Qiita
  2. 投稿
  3. packer

PackerでDockerイメージを作成してQuay.ioにpushする

  • 102
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

Packerを使うとDockerfileを使わずにChefやPuppetからDockerのイメージを作成することができる(詳しくは"Packerを使ってChef/Puppet/AnsibleでDockerのイメージをつくる"に書いた).ChefとかPuppetのような資産が既にある場合は,それを使うのも良い(インフラCIでベースDockerイメージだけChefで作ってしまってみたいなことも考えているが,まだ試し中).

イメージができたら,次はそのイメージをどこかにホストする必要がある.また業務で利用するなら認証機構のちゃんとしたプライベートレジストリを使いたい.Dockerのイメージの保存先の選択肢は,今のところ以下の3つがある.

まず、自分で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は以下のようになる.

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を以下のように書き換える.

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で認証情報を安全に取り扱う方法についても書いた.