Edited at

docker-compose.ymlでcommandの引数が長いのでエスケープして改行したい

More than 1 year has passed since last update.

Dockerフレンドリーなコマンドは設定ファイルなしでも引数でいろいろ挙動が指定できて便利なんだけど、

コマンドの引数の指定が長くなりがちである。

例えばoauth2_proxyはシングルバイナリで、設定ファイルもあるけど、すべての設定が引数で指定できる。

何も考えずに素朴に並べるとこんなかんじで、起動コマンドがクッソ長くなる。


docker-compose.yml

version: '2'

services:
oauth2_proxy:
image: oauth2_proxy
command: /bin/oauth2_proxy -provider="github" -github-org="${OAUTH2_PROXY_GITHUB_ORG}" -github-team="${OAUTH2_PROXY_GITHUB_TEAM}" -http-address="0.0.0.0:4180" -redirect-url="https://upstream/oauth2/callback" -upstream="http://upstream:4440/" -email-domain="*" -cookie-refresh="1h"

圧倒的に読みづらい。

ymlで改行をエスケープするにはどうすればよいのか?

ymlではシェルでおなじみの \ ではなくて > 記号でできる。


docker-compose.yml

version: '2'

services:
oauth2_proxy:
image: oauth2_proxy
command: >
/bin/oauth2_proxy
-provider="github"
-github-org="${OAUTH2_PROXY_GITHUB_ORG}"
-github-team="${OAUTH2_PROXY_GITHUB_TEAM}"
-http-address="0.0.0.0:4180"
-redirect-url="https://upstream/oauth2/callback"
-upstream="http://upstream:4440/"
-email-domain="*"
-cookie-refresh="1h"

圧倒的に見やすい。

ちなみにymlの改行記号には2種類あって、 > だと複数行を空白文字で連結したものとして評価されるんだけど、| 記号だと改行文字で連結したものとして評価されるよう。

ところで Dockerで環境変数を設定ファイルに埋め込むのに便利な envsubst でnginxの設定に環境変数を埋め込もうとすると、必然的にダブルクオートの中が長くなる。

ダブルクオートの中で改行したい場合は、 > で複数行にして空白文字で連結されるから、ダブルクオートの中は \ にすると改行できる。難しい。 (2017/02/05訂正: 改行記号が入るのはダブルクオートではなくインデントが原因でした。難しい)

ダブルクオートの中でも特にインデントしなければ、そのまま単純に並べればよい。


docker-compose.yml

version: '2'

services:
nginx:
image: nginx:alpine
command: >
/bin/sh -c
"envsubst '
$$NGINX_SERVER_NAME
$$NGINX_UPSTREAM_HOST
$$NGINX_UPSTREAM_PORT
'< /etc/nginx/nginx.conf.template
> /etc/nginx/nginx.conf
&& nginx -g 'daemon off;'"
volumes:
- ./nginx.conf.template:/etc/nginx/nginx.conf.template
ports:
- 8080:80
environment:
NGINX_SERVER_NAME: "test.example.com"
NGINX_UPSTREAM_HOST: "hoge"
NGINX_UPSTREAM_PORT: "80"

>の中でインデントすると改行記号が入るよう。インデントしたい場合は、 > で複数行にして空白文字で連結されるから、インデントした場合は \ でエスケープすれば改行できる。難しい。


docker-compose.yml

version: '2'

services:
nginx:
image: nginx:alpine
command: >
/bin/sh -c
"envsubst ' \
$$NGINX_SERVER_NAME \
$$NGINX_UPSTREAM_HOST \
$$NGINX_UPSTREAM_PORT \
'< /etc/nginx/nginx.conf.template \
> /etc/nginx/nginx.conf \
&& nginx -g 'daemon off;'"
volumes:
- ./nginx.conf.template:/etc/nginx/nginx.conf.template
ports:
- 8080:80
environment:
NGINX_SERVER_NAME: "test.example.com"
NGINX_UPSTREAM_HOST: "hoge"
NGINX_UPSTREAM_PORT: "80"

これをデバッグしてて、 docker-compose config という設定ファイルをparseだけしていくれるコマンドがあることに気づいた。エスケープがおかしいときとか、シンタックスエラーとか出る場合に使うとよいのでわないかと。参考までに上記のインデントありのやつをパースするとこんなかんじ。

$ docker-compose config

networks: {}
services:
nginx:
command: "/bin/sh -c\n \"envsubst ' \\\n $NGINX_SERVER_NAME \\\n $NGINX_UPSTREAM_HOST\
\ \\\n $NGINX_UPSTREAM_PORT \\\n '< /etc/nginx/nginx.conf.template \\\n >\
\ /etc/nginx/nginx.conf \\\n && nginx -g 'daemon off;'\"\n"
environment:
NGINX_SERVER_NAME: test.example.com
NGINX_UPSTREAM_HOST: hoge
NGINX_UPSTREAM_PORT: '80'
image: nginx:alpine
ports:
- 8080:80
volumes:
- /Users/m-morita/work/tmp/20170204/nginx.conf.template:/etc/nginx/nginx.conf.template:rw
version: '2.0'
volumes: {}

というわけで、docker-compose.ymlも適切に改行して見やすくしましょう。