Packer + Ansible + ECRを使ったDcokerコンテナイメージ作成の自動化

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

コンニチハ、千葉です。

Dockerコンテナを運用する際、自動化することで沢山のメリットがあります。今回はAWSとも親和性の高い、Packerを利用してコンテナイメージを作成して、ECRへpushしてみました。プロビジョニングツールとしては、弊社で利用頻度の高いAnsibleを使います。

環境

今回は、試しに以下で実施しました。roleはlangesを変更するだけです。

├── ansible
│   ├── group_vars
│   │   └── dev-nginx.yml
│   ├── playbooks
│   │   └── nginx.yml
│   └── roles
│       ├── stage
│       │   └── tasks
│       │       └── main.yml
│       └── system
│           ├── lang
│           │   ├── defaults
│           │   │   └── main.yml
│           │   └── tasks
│           │       ├── main.yml
└── packer-nginx.json

ansibleディレクトリにplaybookを格納します。packer-nbinx.jsonにコンテナイメージの定義や、pushするECRのパラメータを記載します。

Packer用のファイル

packer-nginx.json

ハイライトされているパラメータを適宜変更します。

{
  "variables": {
    "ecr_login_pass": "{{env `ecr_cred`}}",
    "ecr_repo": "XXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/nginx",
    "ecr_url": "https://XXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com",
    "docker_image": "centos:6",
    "ansible_playbook": "ansible/playbooks/nginx.yml",
    "ansible_extra_vars": "--extra-vars env=dev-nginx"
  },
  "builders":[{
    "type": "docker",
    "image": "{{user `docker_image`}}",
    "commit": "true"
    }],
    "provisioners":[
      {
        "type": "shell",
        "inline": [
          "yum -y update",
          "yum -y install epel-release",
          "yum -y install ansible"
        ]
      },
      {
        "type": "ansible-local",
        "playbook_file": "{{user `ansible_playbook`}}",
        "extra_arguments": "{{user `ansible_extra_vars`}}",
        "role_paths": ["ansible/roles/stage","ansible/roles/system"],
        "group_vars": "ansible/group_vars"
      }
    ],
    "post-processors": [
      [
        {
          "type": "docker-tag",
          "repository": "{{user `ecr_repo`}}",
          "tag": "0.7"
        },
        {
          "type": "docker-push",
          "login": true,
          "login_email": "none",
          "login_username": "AWS",
          "login_password": "{{user `ecr_login_pass`}}",
          "login_server": "{{user `ecr_url`}}"
        }
      ]
    ]
  }

ECRログイン時のパスワードは、aws ecr get-login --region us-east-1で取得する必要があります。このパスワードは定期的に変わるので変数で読み込みするように対応しています。"ecr_login_pass": "{{env `ecr_cred`}}"の部分がそれになります。

また"ansible_extra_vars": "--extra-vars env=dev-nginx"を変更することで、環境毎に変数を利用するようにしています。くわしくはこちら

Ansible用のファイル

今回はOSのlangを変更するplaybookで試しました。

ansible/playbooks/nginx.yml

#
# remote-log.yml
#
# ansible-playbook --extra-vars "env=dev-log" remote-log.yml
- hosts: all
  become: yes
  roles:
    - { role: stage }
    - { role: system/lang, tags: ['system'] }

ansible/group_vars/dev-nginx.yml

---
lang: C

ansible/roles/system/lang/defaults/main.yml

---
lang: ja_JP.UTF-8

ansible/roles/system/lang/defaults/main.yml

このroleはAmazon Linuxを想定しています。

---
- name: set LANG={{ lang }} in /etc/sysconfig/i18n
  lineinfile: dest=/etc/sysconfig/i18n regexp=^LANG= line='LANG={{ lang }}' state=present

- name: set locale in /etc/cloud/cloud.cfg (AmazonLinux)
  lineinfile: "dest=/etc/cloud/cloud.cfg regexp='^locale' line='locale: {{ lang }}' state=present"
  when: ansible_distribution == 'Amazon'

ansible/roles/stage/tasks/main.yml

- group_by: key={{ env }}

実行方法

ECRのログインパスワードを変数に格納してから、Packerのコマンドを実行します。

export ecr_cred=$(aws ecr get-login --region us-east-1 | cut -d ' ' -f6)
packer build ./packer-nginx.json

まとめ

PakcerがECRに対応しているので、マネージドでプライベートなコンテナリポジトリを簡単に利用でき運用の手間が減ります。また、Dockerコンテナイメージ作成もコード化で管理できてこれまた、便利です。 AWSでDocker運用するにはかなり強力なツールだと思います。

参考

https://www.packer.io/docs/builders/docker.html