8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

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

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

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

Perl module not enabled with alpine Dockerfile? · Issue #124 · nginxinc/docker-nginx

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

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

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

上記記事にある通り、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

にある通り、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
8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?