クービックではこれまで Vagrantで作成したVMを用いて、ローカルマシンで itamae のテストを実行していました。
管理すべきロールが増えるにつれ毎回テストを回すのがツラくなってきたため、CircleCI による継続的インテグレーションを検討することにしました。
利用環境は以下の通りです。
Env / Tool | Version |
---|---|
OS | Ubuntu 14.04 |
Provisioning | itamae (1.3.6) |
Test | serverspec (2.19.0) |
また、リポジトリの構成は以下の通りです。
cookbooks には Itamae のレシピが、spec にはテストが入っています。
$ tree -L 1
.
├── .ssh
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── circle.yml
├── cookbooks
└── spec
事例調査
CircleCI で Serverspecによるテストの事例をいくつか調査してみました。
Vagrant + EC2
Docker + Serverspec + Itamae
-
[itamaeに入門してDocker調理してみた]
(http://www.slideshare.net/NaokiIshibashi/itamaedocker) -
[Docker on CircleCIでchefのcookbookをserverspecでテスト]
(http://hoppie.hatenablog.com/entry/2015/02/02/014455)
production ではコンテナを利用していないので、prodution と test 環境で乖離が発生するのがやや気になりますが、Docker なら特に追加費用が掛からず、起動も速いので Docker を使うこととしました。
Docker
何はともあれ、ローカルで Docker を動かすための環境を構築します。
Mac OS X であれば、Docker Toolbox を使うのが最もカンタンと思われます。
Docker に触れたことがなければ、Get Started with Docker for Mac OS X を一通り試すのがよいです。
backend
ローカル環境構築が済んだら、docker との I/O を検討します。
Itamae と Serverspec どちらも内部で Specinfra を利用しており、backend として ssh あるいは docker の指定が可能です。production では backend に ssh を利用してるので、docker にも ssh 経由でアクセスすることにします。
なお、Why you don't need to run SSHd in your Docker containers という議論もありますが、コンテナはCircleCIでしか利用しないので今回はよしとしました。
Dockerfile
ssh でアクセスできるようなイメージを準備します。
FROM ubuntu:14.04
RUN apt-get update && apt-get -y upgrade && apt-get install -y build-essential libssl-dev libreadline-dev zlib1g-dev language-pack-ja
RUN apt-get -y install openssh-server ufw curl
RUN mkdir /var/run/sshd
RUN useradd -m docker && echo "docker:docker" | chpasswd && gpasswd -a docker sudo
RUN mkdir -p /home/docker/.ssh; chown docker /home/docker/.ssh; chmod 700 /home/docker/.ssh
ADD ./authorized_keys /home/docker/.ssh/authorized_keys
RUN chown docker /home/docker/.ssh/authorized_keys; chmod 600 /home/docker/.ssh/authorized_keys
CMD /usr/sbin/sshd -D && tail -f /dev/null
工夫したポイントをいくつか。
RUN useradd -m docker && echo "docker:docker" | chpasswd && gpasswd -a docker sudo
で docker ユーザを作成し、sudo グループに登録しています。
CMD /usr/sbin/sshd -D && tail -f /dev/null
/dev/null を tail -f するのは sshd を再起動した際に、コンテナが exit しないための工夫です。
CircleCI
circle.yml を準備します。
machine:
services:
- docker
dependencies:
pre:
- ssh-keygen -t rsa -b 2048 -N "" -C "docker" -f ~/.ssh/id_rsa.docker
- cat ~/.ssh/id_rsa.docker.pub > authorized_keys
- cat .ssh/config >> ~/.ssh/config
- docker build -t kotaroito/ubuntu .
- docker run --privileged -d -p 2222:22 kotaroito/ubuntu
test:
pre:
- env SUDO_PASSWORD=docker bundle exec itamae ssh -h example cookbooks/recipe.rb
override:
- env SUDO_PASSWORD=docker bundle exec rake spec
docker ユーザで ssh するために、ssh-keygen で 秘密鍵・公開鍵を生成して、docker build 時に authorized_keys を image に組み込んでいます。
また、.ssh/config ファイルを用意しておき、itamae ssh -h examle できるようにします。
Host example
HostName localhost
User docker
Port 2222
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /home/ubuntu/.ssh/id_rsa.docker
なお、privileged オプションは itamae で ufw 等を実行する場合に指定する必要があります。
実行結果
無事 CircleCI + Docker で Itamae レシピの継続的インテグレーションをすることができました。
参考サイト
Dockerfile と circle.yml は、以下を参考にさせていただきました。