docker hubのnginxイメージで、起動時環境変数によるproxy_set_header制御を行う

タイトルがうまく表現できないので説明すると、

```:docker-composeで起動する構成
         +-------------------------------------+
         |                                     |
         |    +-------+              +-----+   |
--(req)--|--> | nginx | --(proxy)--> | app |   |
         |    +-------+              +-----+   |
         |                                     |
         +-------------------------------------+
```

このnginxがproxyするリクエストのヘッダーを起動時の環境変数で制御したいという話。

```:指定すればUser-Agentヘッダーを上書き
$ OVERRIDE_UA=iPhone docker-compose up
```

```:指定しない場合は上書きしない
$ docker-compose up
```

appでスマホUAかどうかをチェックしてリダイレクトなどありまして、ローカル開発時はそれをバイパスしたいってのがモチベーション。

# 変更前のDockerファイルとdocker-compose.yml(nginx部分のみ)

```:Dockerファイル
FROM nginx:latest
ADD nginx.conf /etc/nginx/nginx.conf
```

```:docker-compose.yml
services:
  nginx:
    build:
      context: .
      dockerfile: Dockerfiles/proxy
    ports:
     - "80:80"
```

# 1. perlモジュールが使えるnginx:perlイメージを利用する

[library/nginx - Docker Hub](https://hub.docker.com/_/nginx/)

`perl`タグのものだとngx_http_perl_moduleが含まれている。
ただしnginxプロセス起動時にperlモジュールを有効にする必要があるみたいなので、

[Perl module not enabled with alpine Dockerfile? · Issue #124 · nginxinc/docker-nginx](https://github.com/nginxinc/docker-nginx/issues/124)

CMDディレクティブを上書く。

```修正したDockerファイル
FROM nginx:perl
ADD nginx.conf /etc/nginx/nginx.conf
CMD ["nginx", "-g", "daemon off; load_module /etc/nginx/modules/ngx_http_perl_module-debug.so;"]
```

# 2. コンテナに環境変数を引き継ぐ

[Environment variables in Compose | Docker Documentation](https://docs.docker.com/compose/environment-variables/#passing-environment-variables-through-to-containers)

docker-compose.ymlで`environment`を記述すれば環境変数を渡せる。また値を記述しなければdocker-composeコマンド実行時の環境変数が引き継がれる。

```:docker-compose.yml
services:
  nginx:
    build:
      context: .
      dockerfile: Dockerfiles/proxy
    ports:
     - "80:80"
    environment:
     - OVERRIDE_UA
```

# 3. nginx.confで環境変数を読み込む

[nginx.conf で環境変数を読み込む - Qiita](https://qiita.com/dtan4/items/0fe6cca5487698afa68c)

上記記事にある通り、nginx.conf上で環境変数を制御するためにngx_http_perl_moduleが必要だったのです。

```:nginx.confのdiff
--- a/nginx.conf
+++ b/nginx.conf
@@ -1,6 +1,8 @@
 user  nginx;
 worker_processes  1;
 
+env OVERRIDE_UA;
+
 error_log  /var/log/nginx/error.log warn;
 pid        /var/run/nginx.pid;
 
@@ -11,6 +13,8 @@ events {
 
 
 http {
+    perl_set $override_ua 'sub { return $ENV{"OVERRIDE_UA"}; }';
+
     include       /etc/nginx/mime.types;
     default_type  application/octet-stream;
 
@@ -29,6 +33,7 @@ http {
 
     proxy_set_header Host $host;
     proxy_set_header Client-Ip $remote_addr;
+    proxy_set_header User-Agent $override_ua;
 
     server {
       listen 80;
```

# 4. 「上書く」or「上書かない」の制御を行う

[proxy - nginx: Why I can't put proxy_set_header inside an if clause? - Server Fault](https://serverfault.com/questions/506972/nginx-why-i-cant-put-proxy-set-header-inside-an-if-clause)

にある通り、nginx.confのif内ではproxy_set_headerが使えない。値の有無で制御しようと思ったがダメっぽい。
dirtyな方法だと思うが、起動時にコンテナ内でnginx.confを弄る方法をとってみた。

```:run_nginx.sh
perl -pi -e "s/# proxy_set_header User-Agent/proxy_set_header User-Agent/" /etc/nginx/nginx.conf
if [ -z "$OVERRIDE_UA" ]; then
  perl -pi -e "s/proxy_set_header User-Agent/# proxy_set_header User-Agent/" /etc/nginx/nginx.conf
fi

nginx -g "daemon off; load_module /etc/nginx/modules/ngx_http_perl_module-debug.so;"
```

```:Dockerファイル
FROM nginx:perl
ADD nginx.conf /etc/nginx/nginx.conf
ADD run_nginx.sh /
CMD ["sh", "/run_nginx.sh"]
```

# 5. 実行

これで期待した制御が実現できた。

```:指定すればUser-Agentヘッダーを上書き
$ OVERRIDE_UA=iPhone docker-compose up
```

```:指定しない場合は上書きしない
$ docker-compose up
```