Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

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

mercari
フリマアプリ「メルカリ」を、グローバルで開発しています。
https://tech.mercari.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away