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

そんな今日この頃の技術ネタ

本家側に書くほどでもない小ネタ用

envsubstを使ってShellでテンプレートエンジン的なことをする、Dockerコンテナ起動時にファイルを生成する

毎回の起動時に外部から指定された文言を含んだHTMLファイルを生成して、以降はそれを返すようなDockerイメージを作りたいという案件があった。

一度コンテナを起動してしまえば完全にスタティックなページなのでわざわざMySQL等には繋ぎたくないし、 ファイルを置いたボリュームをマウントするという手もあるがホストが複数台なので管理がめんどくさい。

できることならコンテナの起動時に環境変数として値を渡すようなDocker的にお行儀の良い方法をとりたいが、 文字列結合でHTMLファイルを生成するのもかったるい。


要件的には何がしかの言語のテンプレートエンジンを使えばよいところではあるが、 本当に一文だけなんでそれだけのためには大げさだよなぁ何か無いかなぁと思ってググッていたら、 envsubst なるものをみつけた。

どうやら環境変数を埋め込んだ出力ができるらしい。

$ export var1=hoge var2=fuga
$ cat << 'EOF' |envsubst 
${var1}から${var2}
EOF

hogeからfuga

※ブコメに指摘があったのでシングルコーテーションで括る形に修正。確かに単にヒアドキュメントだと環境変数展開されちゃうから例として不適切だっった。ご指摘ありがとうございます!

これを使用して、コンテナ起動時に指定した文言のHTMLを生成するようなイメージを作成することにした。

導入

gettext なるパッケージを入れれば良いらしい。

$ apt-get update&&apt-get install gettext

サクッとapt-getで導入できる。(同様にyumでも入るそうだ。)

テンプレートファイル

置き換えたい部分を環境変数として記述したテンプレートファイルindex.html.tmpを用意した。

<html>
  <head><title>テンプレートテスト</title></head>
  <body>${GEN_TEXT}</body>
</html>

上記のファイルにおける${GEN_TEXT}の部分が環境変数GEN_TEXTで置き換わる。


試しに実行してみる。

$ export GEN_TEXT="本日は晴天なり"
$ cat index.html.tmp | envsubst > index.html
$ cat index.html
<html>
  <head><title>テンプレートテスト</title></head>
  <body>本日は晴天なり</body>
</html>

意図したHTMLファイルが生成された。

Dockerfileへの記載、Dockerでの使用

蛇足っちゃ蛇足だが一応。

# envsubstをインストール
RUN apt-get update && apt-get install -y gettext

# テンプレートファイルをコンテナに入れる
ADD /host/path/index.html.tmp /container/path/

また、コンテナのエントリーポイント的な役割のスクリプトに生成コマンドを記述しておく。

#!/bin/bash

# 置かれたテンプレートからHTMLファイルを生成
cat /container/path/index.html.tmp | envsubst > /container/path/index.html

# あとは本来の処理の記述

あとは起動時に

$ docker run -e GEN_TEXT="本日は晴天なり" something_image

みたいな感じで環境変数オプションとして渡せば良い。


今回はHTMLファイル生成なんかに使ったけれど、例えば設定ファイルの記述なんかにも使えそう。

というか僕が知らなかっただけで世間的にはポピュラーな方法だったのかもしれない。

nginxのDockerイメージでサンプル作ろうと思ったら元々envsubst入ってたし。


コンテナの外側の話になるけど、開発メンバー間でほとんど同じdocker-compose.yml使いまわしたいけど一部だけ記述変えなきゃいけないのどうしようと思ったけど、ここでもenvsubst使えば楽できるかもな―ってこの記事書いてて思った。