目的が違うのに強引過ぎるだろ〜
オンプレからAWSに移行(しかもオートスケール構成にしにくい負債プロジェクトとか・・・)する際に、dockerではなくec2を使う場合、ローカルはどうするか。できればdockerにしたいですよね。
amazonlinuxのdocker imageはamazonが公式に提供しているので、これを使いたいですね。
https://hub.docker.com/_/amazonlinux/
amazonlinuxでないと、yum.repoでインストールできるバージョンが全然違いますし、apache2.4なんかは実はamazonエディションだったりするので、ec2とdockerで合わせたいものです。
最終的に、オンプレに優しいansibleをdockerと組み合わせると、↓こんな感じでしょうか。オンプレもdockerも両方イケるぜ〜、な構成です。
環境 | サーバ種別 | OS | プロビジョニング |
---|---|---|---|
ローカル | docker or vagrant | amazonlinux | ansible |
production | ec2 | amazonlinux | ansible |
こうしたいのですが、amazonlinuxのdocker imageは、ec2上のamazonlinuxと大分構成が異なり、単純にec2に適用していたplaybookをdockerに適用しても、エラーが出まくりで心が折れてしまいます。
今回はそのDockerfile周りのエラー祭りを何とかしていこうと思います。
目的
production環境はec2 + amazonlinux。
ローカル環境はdocker or vagrant + amazonlinuxとしたい。
どっちにもansibleのplaybookでプロビジョニングができるようにしたい。
環境
種別 | バージョン |
---|---|
amazon linux | 2017.09 |
ansible | v2.4.0.0 |
docker | v 17.09(docker for mac) |
Dockerfileでエラーになるもの
グループ・ユーザ追加ができないんですけど・・・?
「よーし、まずはグループとユーザ追加するか〜」
RUN groupadd hoge
↓
/bin/sh: groupadd: command not found
「!?」
いきなり洗礼を受けます。docker imageのamazonlinuxにはgroupadd, useraddコマンドありませんから〜!!
両コマンドを使えるようにするには、shadow-utilsをインストールします。
RUN yum install -y shadow-utils
sudoが無いんですけど・・・?
無いんだなこれが。
RUN yum install -y sudo
/etc/ssh/が無いんですけど・・・?
dockerへはsshしませんが、ec2のamazonlinuxにプロビジョニングする際に各種ssh関連ファイルが必要なので、用意しておく必要があります。
RUN yum install -y openssh-server
pipが無いんですけど・・・?
TASK [ansible : install ansible] *********************************************************************************************************** fatal: [dev_server_1]: FAILED! => {"changed": false, "failed": true, "msg": "Unable to find any of pip2, pip to use. pip needs to be installed."}
2手間必要になります。
RUN yum install -y python27-setuptools
RUN easy_install pip
これでPython2.7版のpipが使えるようになります。但しインストールパスの関係上sudoが必要になります。
pipのパスが通ってないんですけど・・・?
RUN ln -sf /usr/local/bin/pip /usr/bin/pip && \
作業ユーザでパス無しsudoしたいんですけど・・・?
RUN echo "hoge ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/hoge
clockファイルが無いんですけど・・・?
ln: /etc/sysconfig/clock: No such file or directory
まーじか。
↓こうします。
RUN echo 'ZONE="Asia/Tokyo"' > /etc/sysconfig/clock && \ rm -f /etc/localtime && \ ln -fs /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ echo "LANG=\"en_US\"" > /etc/sysconfig/i18n
パス無し鍵認証の準備だけしたいんですけど・・・?
ec2のamazonlinuxの時と同様に鍵認証でsshできるようssh関連ファイル諸々を用意しておきます。
/etc/sshが無かったりsedで頑張ったり、ちょっと面倒臭いです。
ENV WORK_GROUP="hoge" \ WORK_USER="fuga" RUN groupadd ${WORK_GROUP} && \ useradd -c "${WORK_USER} user" -d "/home/${WORK_USER}/" -g ${WORK_GROUP} -G ${WORK_GROUP},td-agent ${WORK_USER} && \ mkdir -p /home/${WORK_USER}/.ssh && \ chown ${WORK_USER}:${WORK_GROUP} /home/${WORK_USER}/.ssh && \ chmod 700 /home/${WORK_USER}/.ssh && \ sed -ri 's/#PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config && \ sed -ri 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config ADD ./docker.pem.pub /home/${WORK_USER}/.ssh/authorized_keys RUN chown ${WORK_USER}:${WORK_GROUP} /home/${WORK_USER}/.ssh/authorized_keys && \ chmod 600 /home/${WORK_USER}/.ssh/authorized_keys
FOREGROUND起動するものが無いんですけど・・・?
dockerは通常フォアグラウンドで起動し続けなければ、実行したコンテナは即座に終了してしまいますね。
そこで以下のように小細工をする事で、「無を無限にtailする」というちょっと哲学的な事をすると、無理矢理フォアグラウンド起動し、ansibleをぶつける事ができるようになります。
ENTRYPOINT tail -f /dev/null
ansibleは起動中のコンテナに対してしかプロビジョニングできないので、何とかしてフォアグラウンドで起動させ続ける必要があるのです。
ansibleのインベントリとplaybookのhostsどう書くの・・・?
まず前提として、Docker Connection Pluginを利用します。dockerでsshdを動かすのは何かと面倒なので、ssh関連ファイルがあるだけでsshしないコンテナを用意し、ansibleはconnection pluginで接続します。(Connection Pluginは恐らくdocker execしてるだけ)
さあ、これでコンテナはフォアグラウンドで起動し、playbookを叩く準備が整いました。
後は接続先を調整するのみです。
インベントリ
[local] container_name [all:children] local
playbook
- hosts: local roles: - fabric
localの部分はどんな名前でもよくて、ホスト名はdockerのコンテナ名とします。dockerコンテナは起動中である必要があるので、前述したように、フォアグラウンドで起動し続けておく必要があります。
最後に、以下でplaybookを実行すれば、今までec2上のamazonlinuxに適用していたplaybookを、ローカルのdockerに適用する事ができます。
ansible-playbook \ --connection=docker \ -i inventory.ini \ playbook.yml
connection節をplaybook側に書くという方法もありますが、いずれによ、右辺の部分は変数化しておき、環境によってconnection=local, connection=docker等と切り替える事ができるようにしておくといいと思います。
おまけ:Vagrantでamazonlinux!
docker imageには公式のイメージがありました。
vagrantはどうか?残念ながらありません。
但し、以下が配布されています。
AMIのバージョンが2017.03になっているので、自分で/etc/yum.confをいじってAMIのバージョンを2017.09等にすると、最新AMIのyum.repoを利用可能になります。
ただし、VBoxGuest周りが正しくインストールできていない?っぽく、vagrant upの/vagrantマウント時にエラーが出てしまいます。その状態でもvagrant ssh自体は可能です。