FargateのNginxコンテナの環境変数デバッグ方法

やること

前回、FargateのApacheコンテナでの環境変数のデバッグ方法について書きました。

FargateのApacheコンテナの環境変数デバッグ方法

今回はFargateのNginxコンテナにて、環境変数のデバッグ方法をご紹介します。

方針

NginxでもApacheと同様、アクセスログに環境変数値を出力することができます。
ただし、Apacheと違い直接アクセスログに環境変数を指定することはできません。Perlモジュールを介してNginx変数に変換するというステップが必要になります。
変数を埋め込んだアクセスログを標準出力に出力し、それをCloudWatch Logsに転送し確認します。

具体的な手順

今回はNGINX_ENV_TEST1NGINX_ENV_TEST2という環境変数の中身を確認することとします。

コンテナの用意

perl モジュールを含んだDockerイメージを使う

nginx:perl など perl モジュールを含んだDockerイメージを使います。
※後からモジュール追加もできる様ですが、今回は未調査です。

$ docker run -d --name nginx-with-perl nginx:perl

デフォルト conf ファイル取得

$ docker cp nginx-with-perl:/etc/nginx/nginx.conf ./

perl モジュールを有効化する

nginx.conf の main コンテキスト内かつ、各ブロック(events, http, stream, mail)より前に load_module "modules/ngx_http_perl_module.so"; 行を追加します。

  error_log  /var/log/nginx/error.log warn;
  pid        /var/run/nginx.pid;
 
+ load_module "modules/ngx_http_perl_module.so";
  
  events {
      worker_connections  1024;
  }

環境変数定義

nginx.conf内を2箇所変更します。

env (環境変数名);行を追加

Nginxはデフォルトで親プロセスの環境変数を引き継ぎません。
まずは親プロセスの環境変数を引き継げる様に、 main コンテキスト内に envディレクティブを追加します。

  events {
      worker_connections  1024;
  }
  
+ env NGINX_ENV_TEST1
+ env NGINX_ENV_TEST2;
    
  http {
      include       /etc/nginx/mime.types;

perl_set $(変数名) 'sub { return $ENV{"(環境変数名);"}; }'; 行を追加

nginx.conf の http コンテキスト内で perl_setディレクティブ を使用し、perl変数を定義します。

  http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;
  
+     perl_set $test_val1_from_env 'sub { return $ENV{"NGINX_ENV_TEST1"}; }';
+     perl_set $test_val2_from_env 'sub { return $ENV{"NGINX_ENV_TEST2"}; }';
  
      log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '

ログフォーマット変更

上記で定義した変数をログに出力する様に、フォーマットを変更します。

  http {
      include       /etc/nginx/mime.types;
      default_type  application/octet-stream;
  
      perl_set $test_val1_from_env 'sub { return $ENV{"NGINX_ENV_TEST1"}; }';
      perl_set $test_val2_from_env 'sub { return $ENV{"NGINX_ENV_TEST2"}; }';
  
      log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
-                       '"$http_user_agent" "$http_x_forwarded_for"';
+                       '"$http_user_agent" "$http_x_forwarded_for" '
+                       '$test_val1_from_env $test_val2_from_env';
  
      access_log  /var/log/nginx/access.log  main;

access_log ディレクティブで上記フォーマットを使用

今回はもともと使用する設定になっているmainのフォーマットを変更したため、特に修正は不要です。

ローカルでデバッグ

イメージのビルド

$ docker image build . -t nginx-env-test

コンテナ作成

-eで環境変数を宣言できます。
NGINX_ENV_TEST1localNGINX_ENV_TEST2dayoを定義しています。

$ docker run -p 8080:80 --name nginx-env-test-container -e NGINX_ENV_TEST1=local -e NGINX_ENV_TEST2=dayo nginx-env-test

タスク定義で環境変数を設定

ECRにイメージをプッシュした後、タスク定義でそのイメージを使用します。
コンテナの編集の環境変数欄にて、環境変数を定義します。 NGINX_ENV_TEST1fargateNGINX_ENV_TEST2yadeを定義しています。 コンテナの編集の環境変数欄にて、環境変数を定義 ログドライバーでawslogsを設定することも忘れずに。

CloudWatch Logs で確認

コンテナが立ち上がったのち、しばらくしてCloudWatch Logsにアクセスログが表示されます。
環境変数値が表示されていることが確認できました。 CloudWatch Logsに表示されるアクセスログに環境変数の表記あり

まとめ

Fargate上で動くNginxコンテナでの環境変数のデバッグ方法についてご紹介しました。
Nginxはデフォルトで親プロセスの環境変数を引き継がないので、まずenvディレクティブで引き継ぐ様にします。
次に、環境変数をそのまま参照することができないのでperl変数化します。
その変数をアクセスログフォーマットで使用し、CloudWatch Logsに転送する様にすれば、デバッグ可能です。
ちょっとステップが多くて面倒ですが、必要になった時にご参考くださいませ。

参考情報