VTRyo Blog

一歩ずつ前に進むブログ

PackerとAnsibleでDocker imageを作る

f:id:vtryo:20180716122058p:plain

ども。最近ハイペースでブログ書いています。

先日ansible containerでがんばってdocker image作成する話を書きました。

Ansibleで管理している構成をdocker imageに固めたいという要件があったのでansible containerをやっていたのですが、これより良い方法があったので書いときます。

Packerとは

Packerとは、Hashicorp社が提供しているサービスです。

Modern, Automated

HashiCorp Packer is easy to use and automates the creation of any type of machine image. It embraces modern configuration management by encouraging you to use automated scripts to install and configure the software within your Packer-made images. Packer brings machine images into the modern age, unlocking untapped potential and opening new opportunities.

ちょっと前はAWSなんかのAMIを自動で作成したりというイメージだったのですが、Dockerがより普及してきてからはDocker imageをPackerで管理したりビルドしたりする人も増えてきたのかなと思います。

Packer + ansible

vagrantでansible使ったことがある人ならピンとくるかもしれないですね。

今回はansible-localを使ってコンテナそのものにansibleを実行させます。この方法がきれいなのかはちょっと審議(ansibleをインストールさせる手間があるから)

Ansible好きだしAnsibleで運用しているものが多いので、そいつでdocker imageに固められるなら結構よいです。

やってみる

いつもの通りローカル環境はMacbookです。

  • packerインストール
% brew install packer
% packer version
Packer v1.2.2

container.json

packerが読み込むファイルです。
ちなみにファイル名はなんでも良いです。

{
  "builders": [{
      "type": "docker",
      "image": "centos:7",
      "export_path": "image.tar"
    }],
  "provisioners":[{
      "type": "shell",
      "inline": [
        "yum -y update",
        "yum -y install epel-release",
        "yum -y install python-pip",
        "pip install --upgrade pip",
        "pip install ansible==2.5.0"
      ]}, {
      "type": "ansible-local",
      "playbook_file": "container_base.yml"
    }],
  "post-processors": [{
      "type": "docker-import",
      "repository": "ansible-dockerimage",
      "tag": "0.1.0"
    }]
}

ちょっと簡単に解説を入れておきます。

  • builders:

どうビルドするか定義する箇所です。

typeでdockerを指定することでdocker imageを扱える
imageにはpullするベースとなるコンテナを指定
export_pathはイメージを出力名

  • provisioners:

イメージに対してどうプロビジョニングするか定義する箇所です。

typeでプロビジョニングする方法を指定。今回はshellとAnsibleをそれぞれ指定
ansible-localでコンテナ自身にAnsibleを実行させる

  • post-processors:

構築したイメージの後処理を定義する箇所です。

・docker imageとしてビルドするのでdocker-importを指定

container_base.yml

container.jsonに書かれたplaybook_file部分に記述されたファイルの内容です。
同じくファイル名はなんでも良いですが、playbook_fileに記述されている名前とあわせましょう。

ちょっと挙動がみたいだけなので簡単なインストールだけにしておきました。

- hosts: all
  become: True
  tasks:
    - name: install package
      yum: name={{ item }} state=present
      with_items:
        - git
        - htop

ビルド

packerでビルドします。

% packer build container.json
docker output will be in this color.

==> docker: Creating a temporary directory for sharing data...
==> docker: Pulling Docker image: centos:7

(略)

docker: Collecting pip
docker:   Downloading pip-9.0.3-py2.py3-none-any.whl (1.4MB)
docker: Installing collected packages: pip
docker:   Found existing installation: pip 8.1.2
docker:     Uninstalling pip-8.1.2:
docker:       Successfully uninstalled pip-8.1.2
docker: Successfully installed pip-9.0.3
docker: Collecting ansible==2.5.0

(略)

docker:
docker: PLAY [all] *********************************************************************
docker:
docker: TASK [Gathering Facts] *********************************************************
docker: ok: [127.0.0.1]
docker:
docker: TASK [install package] *********************************************************
docker: changed: [127.0.0.1] => (item=[u'git', u'htop'])
docker:
docker: PLAY RECAP *********************************************************************
docker: 127.0.0.1                  : ok=2    changed=1    unreachable=0    failed=0
docker:
==> docker: Exporting the container
==> docker: Killing the container: xxxxxxxxxxxxxxx
==> docker: Running post-processor: docker-import
docker (docker-import): Importing image: Container
docker (docker-import): Repository: ansible-dockerimage:0.1.0
docker (docker-import): Imported ID: sha256xxxxxxxxxxxxxxxxx
Build 'docker' finished.

==> Builds finished. The artifacts of successful builds are:
--> docker: Imported Docker image: ansible-dockerimage:0.1.0

無事完了!

  • docker imagesにあるか確認してみる
% docker images
REPOSITORY                             TAG                 IMAGE ID            CREATED             SIZE
ansible-dockerimage                    0.1.0               6af5e04ddc32        25 minutes ago      467MB

(CREATEDのタイムが経過しているのはブログ執筆の関係です^^;)

ログインしてみる

% docker run -it 6af5e04ddc32 /bin/bash
[root@8e9de3152e7e /]#
[root@8e9de3152e7e /]# htop
[root@8e9de3152e7e /]# git
usage: git [--version] [--help] [-c name=value]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

The most commonly used git commands are:
   add        Add file contents to the index
   bisect     Find by binary search the change that introduced a bug
   branch     List, create, or delete branches
   checkout   Checkout a branch or paths to the working tree
   clone      Clone a repository into a new directory
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   fetch      Download objects and refs from another repository
   grep       Print lines matching a pattern
   init       Create an empty Git repository or reinitialize an existing one
   log        Show commit logs
   merge      Join two or more development histories together
   mv         Move or rename a file, a directory, or a symlink
   pull       Fetch from and merge with another repository or a local branch
   push       Update remote refs along with associated objects
   rebase     Forward-port local commits to the updated upstream head
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index
   show       Show various types of objects
   status     Show the working tree status
   tag        Create, list, delete or verify a tag object signed with GPG

'git help -a' and 'git help -g' lists available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.
[root@8e9de3152e7e /]#

インストールしたものが実行できましたね!

おわりに

実際に運用されているAnsibleはもっとごりごりに複雑なので、それぞれのコンテナにプロビジョニングする必要があります。

とはいえ、先日試行したansible containerとは比べ物にならないほど楽っすねw

blog.vtryo.me

参考

Packer+AnsibleによるAMIの作成 | Developers.IO

Dockerfile の代わりに Packer を使って Docker に再々入門してみている - えいのうにっき