読者です 読者をやめる 読者になる 読者になる

notebook

都内でWEB系エンジニアやってます。

docker-compose でHOSTごとに代わる設定を適用する

今回はdocker-composeを使ってもう少し色々やってみます

例としてdockerでmkdocs + elasticsearchを起動し、mkdocsのテキストをelasticsearchから検索できるようにします

f:id:swfz:20160819001208p:plain

やることは2点

  • docker-compose起動(環境変数経由でhost ipを渡す)
  • Dockerfile内で環境変数を参照してアプリケーションからのAJAXリクエスト先のIPをhost ipに設定できるようにする

実際に公開するアプリケーションであればドメインとってそれを指定すればOKだと思います

開発とかで使う場合/etc/hostsを編集しても対応できると思いますが、複数の環境で/etc/hostsをいじるのもどうかと思ったので実現できる方法を探してみたところなんとかなったので備忘録を兼ねて残しておきます

環境変数を渡す

docker-composeで環境変数を用いる方法

docker-composeの設定ファイルで${}という形で変数を受け取れます

  • docker-compose.yml
environment:
  - ES_ENDPOINT=${HOST_IP}

という形に設定してDockerfileでES_ENDPOINTを参照できるようにします

$ HOST_IP=`hostname -I | awk '{print $2}'`
192.168.100.12
$ HOST_IP=`hostname -I | awk '{print $2}'` docker-compose up

コマンドでHOST_IPを渡します

shellscriptのようにデフォルト値を与えることが出来ないようなので環境変数を渡すのが必須にはなってしまうようです。。。

下記参照

Compose File Reference docs.docker.com

余談ですがリファレンスの日本語化プロジェクトもあるようです

Compose ファイル・リファレンス — Docker-docs-ja 1.12.RC ドキュメント http://docs.docker.jp/compose/compose-file.htmldocs.docker.jp

dockerコンテナ起動時の前処理(テンプレートレンダリング)

entrykitを使います

Entrykit のすすめ - Qiita

qiita.com

ほぼここに書いてある通りです

サーバ上にajaxリクエストを送る部分があるのでそのリクエスト先を環境変数から参照させて環境によって変更するために使います

まずDockerのコンテナ上にentrykitをインストールします

  • Dockerfile
ENV ENTRYKIT_VERSION 0.4.0

RUN curl -LO https://github.com/progrium/entrykit/releases/download/v${ENTRYKIT_VERSION}/entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz && \
    tar zxvf entrykit_${ENTRYKIT_VERSION}_Linux_x86_64.tgz && \
    mv entrykit /bin/entrykit && \
    chmod +x /bin/entrykit && \
    entrykit --symlink

テンプレートを使って変数を差し込む箇所を記述します

  • config.js.tmpl
define(function() {
  return {
    esEndpoint: "{{ var "ES_ENDPOINT" | default "localhost" }}"
  }
});

ES_ENDPOINTをdocker-compose.ymlから渡しているのでそれを参照させます

entrykitを用いて前処理を追加します

  • Dockerfile
COPY config.js.tmpl /config.js.tmpl

ENTRYPOINT [ \
  "render", "/config.js", "--", \
  "prehook", "cp /config.js /docs/sample/custom/js/config.js", "--", \
  "bash", "/entrypoint.sh" \
]

renderで/config.jsに配置してprehookでアプリケーションが読み込む場所に配置しています

これはVOLUMEで指定したディレクトリ以下にconfig.jsを直接配置するとコンテナ起動時にファイルが存在しない旨のエラーになったために行いました

render処理してからvolumeへのマウントが行われている...?

なのでprehook時に移動してあげるようにしました

まとめ

entrykitいいねって話になってしまいましたが便利だと思います

こういうパターンはよくありそうですし

prehook,render以外にも使えるコマンドがあるので機会があれば使ってみたいです

実際のコードはこちら

swfz/docker-mkdocs

github.com