Edited at

Docker + Alpine LinuxでMustacheを使う

More than 1 year has passed since last update.

最近はテンプレートを使った簡易な処理を書くのにMustacheを多用しています。Mustacheはシンプルなテンプレートエンジンで、各言語に実装が存在するので一度書き方を覚えてしまえば多くの言語で同じテンプレートを使える事が利点です。公式には以下の言語に対応していると記載があります。


Available in Ruby, JavaScript, Python, Erlang, node.js, PHP, Perl, Perl6, Objective-C, Java, C#/.NET, Android, C++, Go, Lua, ooc, ActionScript, ColdFusion, Scala, Clojure, Fantom, CoffeeScript, D, Haskell, XQuery, ASP, Io, Dart, Haxe, Delphi, Racket, Rust, OCaml, Swift, Bash, Julia, R, Crystal, and for Common Lisp


今回はDocker + Alpine Linux + Nginxでnginx.confの一部を環境によって書き換えたいと考えて、いつも使っているbashのMustacheで処理を書きましたが、標準のAlpine LinuxのDockerイメージにはbashが入っていないので使えませんでした。

何か良い方法がないか探していると、shでMustacheを使えるライブラリがありました。これはshの関数だけで作られているので、関数をロードすれば基本的にどの環境でも動く可能性があります。定義ファイルは8kb弱なのでとても軽いですね。

rcrowley/mustache.sh: Mustache in POSIX shell


使い方

./lib/mustache.sh をロードするだけて使えるので、このファイルとLICENSEファイルをDockerイメージに含めれば良いのではないでしょうか。

$ git clone git@github.com:rcrowley/mustache.sh.git

$ sh
$ cd mustache.sh
$ source ./lib/mustache.sh
$ echo 'Hello, {{NAME}}!' | NAME=world mustache
Hello, world!

{{{}}} の表記には対応していませんでした。大体の機能が動作することは確認できていますが、一部動作しないものもあるかもしれません。

$ echo 'Hello, {{{NAME}}}!' | NAME=world mustache

Hello, {world}!


Alpine Linux + Nginxでnginx.confを書き換えるサンプル

nginx.confのworker_processesを書き換えてみます。


ファイル構成

$ tree . -N

.
├── Dockerfile
├── bin
│   └── run
├── conf
│   └── nginx.conf.mustache
└── lib
├── LICENSE # mustache.sh/LICENSE
└── mustache.sh # mustache.sh/lib/mustache.sh

3 directories, 5 files

Dockerfile

FROM nginx:1.8.1-alpine

WORKDIR /opt/alpine-nginx/current

RUN mkdir bin lib conf
COPY bin/* bin/
COPY lib/* lib/
COPY conf/* conf/

CMD ["./bin/run"]

bin/run

Mustacheでテンプレートを置換する処理を挟んでNginxを起動。

#!/bin/sh

cd $(dirname $0)/..

. lib/mustache.sh
cat conf/nginx.conf.mustache | mustache > /etc/nginx/nginx.conf

nginx

conf/nginx.conf.mustache

NGINX_WORKER_PROCESSESの環境変数を置換するように設定。

user  nginx;

worker_processes {{NGINX_WORKER_PROCESSES}};
daemon off;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

include /etc/nginx/conf.d/*.conf;
}


動作確認

イメージをビルド。

$ docker build -t qiita/alpine-nginx-mustache .

Sending build context to Docker daemon 17.41 kB
Step 1 : FROM nginx:1.8.1-alpine
---> c0dddb65129b
Step 2 : WORKDIR /opt/alpine-nginx/current
---> Running in 65f2ea41af52
---> 3bf3081ecaba
Removing intermediate container 65f2ea41af52
Step 3 : RUN mkdir bin lib conf
---> Running in 900c7bcebf4c
---> 30d34bca8070
Removing intermediate container 900c7bcebf4c
Step 4 : COPY bin/* bin/
---> e7b0b96841ea
Removing intermediate container 1d5645839d05
Step 5 : COPY lib/* lib/
---> a3d1b4f303b3
Removing intermediate container 71c6455716bd
Step 6 : COPY conf/* conf/
---> 14f3d7204e7b
Removing intermediate container 58485eff3fb8
Step 7 : CMD ./bin/run
---> Running in ee7c082b2e69
---> 634865d06deb
Removing intermediate container ee7c082b2e69
Successfully built 634865d06deb

コンテナを起動。

$ docker run -d -e NGINX_WORKER_PROCESSES=2 -p 80:80 qiita/alpine-nginx-mustache

e141b6fed6d10b4e120f11277ca21b0d235024ef8313f35f7be17a82146ca819

コンテナの動作確認。

$ curl -I http://$(docker-machine ip default)

HTTP/1.1 200 OK
Server: nginx/1.8.1
Date: Mon, 25 Apr 2016 21:55:17 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 05 Apr 2016 19:06:11 GMT
Connection: keep-alive
ETag: "57040ca3-264"
Accept-Ranges: bytes

worker_processesがNGINX_WORKER_PROCESSESの値に書き換わっていることを確認。

$ docker exec -it e141b6fed6d10b4e120f11277ca21b0d235024ef8313f35f7be17a82146ca819 head -n 2 /etc/nginx/nginx.conf

user nginx;
worker_processes 2;