envsubstを使用してNginx Dockerイメージに環境変数を埋め込む
2024-08-02
この記事では、Webサーバーの1つであるNginxでダイナミックな環境変数をサポートするようにDockerイメージを構成する方法に焦点を当てます。これにより、より柔軟なフロントエンドのデプロイを実現することができます。
しかし、その前に、Nginx自体についての簡単な紹介と、いつ使用すべきか、いつ使用すべきでないか、フロントエンドの配信でNginxを使用する理由について説明します。
Nginxとは?
Nginxは人気のあるオープンソースの Web サーバーソフトウェアで、リバースプロキシ、ロードバランサー、メールプロキシ、および HTTP キャッシュとしても機能します。
いつ使用すべきか?
Nginxは、いくつかのシナリオで優れた性能を発揮する多用途なWebサーバーです:
- 高トラフィックのウェブサイト Nginxは多数の同時接続を効率的に処理し、忙しいサイトに最適です。
- 静的コンテンツの配信 画像、CSS、JavaScriptなどの静的ファイルを迅速に配信します。
- ロードバランシング Nginxはトラフィックを複数のサーバーに効果的に分散し、信頼性とパフォーマンスを向上させます。
- リバースプロキシ アプリケーションサーバーの前に配置し、キャッシングやSSL終端などの機能を追加します。
- API ゲートウェイ Nginxは分散アーキテクチャ内の異なるマイクロサービスへのリクエストルーティングに適しています。
- パフォーマンス最適化 キャッシング機能により、Nginxはウェブサイトの速度を大幅に向上させます。
- 高度なセキュリティ レート制限などの機能により、特定の種類の攻撃から保護します。
いつ使用を避けるべきか?
Nginxは強力で多用途なWebサーバーですが、適さないシナリオもあります:
- シンプルで低トラフィックのウェブサイト 基本的なウェブサイトにはNginxの高度な機能は過剰かもしれません。Apache HTTP Serverのようなシンプルなサーバーの方が設定と管理が簡単かもしれません。
- Windowsベースの環境 NginxはWindows でも動作しますが、主にUnix系システム向けに設計されています。Windows 中心の環境では、IIS (Internet Information Services) の方が自然な選択かもしれません。
- .htaccess サポートが必要な場合
Apache HTTP Serverとは異なり、Nginxは
.htaccess
ファイルをサポートしていません。アプリケーションが.htaccess
に大きく依存している場合、Nginxに移行するには大幅な変更が必要です。 - Webサーバーとの深い統合が必要なアプリケーション 特定のWebサーバーと緊密に連携するように構築されたアプリケーションがあります。別の Web サーバーのアーキテクチャに密接に結び付いているアプリケーションをNginxに移行するのは困難です。
- リアルタイム通信が主な要件の場合 NginxはWebSockets を扱えますが、リアルタイムの双方向通信に主に焦点を当てたアプリケーションには、Node.jsとSocket.IOのような専門的なソリューションがより適しているかもしれません。
- 社内の専門知識が限られている場合 他のWeb サーバーに慣れているチームの場合、Nginxの学習曲線はシンプルなプロジェクトにはあまり価値がないかもしれません。
- GUI ベースの管理が広範に必要な場合 Nginxには管理用の組み込みGUIがありません。非技術スタッフが Web サーバーを管理する必要がある環境では、包括的なグラフィカルインターフェースを備えたソリューションが好まれるかもしれません。
なぜNginxをフロントエンド配信で使うか?
今までRe:Earthでは、フロントエンドをデプロイする方法として、ソースコードをGCS(Google Cloud Storage)のバケット上に配置し、CDN経由でそれらの配信を行っていました。
ところがこの方法では、次の問題が発生するようになりました。
- フロントエンドをgsutil rsyncでデプロイしているため、何らかの理由で途中でデプロイが中断されると、バケット上のファイルが中途半端な状態になる可能性がある。また、デプロイ中にユーザーのアクセスがあると、すべてのファイルが揃っていない状態でファイルが配信される可能性がある。
- 新バージョンのデプロイ後にフロントエンドにバグが発見されたときに、迅速にロールバックすることが難しい。
- GCS上で簡単にロールバックできる仕組みを構築しようとすると、CI/CDのワークフローやスクリプトが煩雑になる。
そのため、Nginxでフロントエンドのファイルを配信するようにし、そのDockerイメージをCloud Runにデプロイする方法へ移行することを計画しています。
この方法により、以下のメリットを得られます。
- CI/CDのワークフローがシンプルになる。
- Cloud Runの機能で簡単にフロントエンドのロールバックやトラフィックの変更が可能になる。中途半端な状態はなくなり、ダウンタイム無しでリビジョンの切り替えが可能になる。
- Cloud Deployを導入し、フロントエンド含めてカナリアリリースの実現が可能になる。
この方法は、フロントエンドの配信においてGCSのスケーラビリティの恩恵を受けられなくなるというデメリットはありますが、それ以上にメリットが大きいと考えました。
ただし、これを実現するためには、Nginxイメージが環境変数を通していくつかの設定をカスタマイズできる機能を持つ必要があります。これがないと、1つでも設定を変更する度にDockerイメージの再ビルドが必要になってしまいます。
シンプルなNginx Dockerイメージを作成する
基本的なNginx Docker イメージを作成するために、公式のnginxイメージを出発点として使用します。設定方法は以下の通りです。
はじめに、プロジェクト用の新しいディレクトリを作成します:
mkdir nginx-docker
cd nginx-docker
Dockerfileを作成します:
touch Dockerfile
好きなテキストエディタで Dockerfile を開き、以下の内容を追加します:
FROM nginx:alpine
COPY ./nginx.conf /etc/nginx/nginx.conf
COPY ./html /usr/share/nginx/html
Dockerfileの内容は以下の通りです:
- 公式のNginx Alpineイメージをベースとして使用
- カスタムnginx.confファイルをコンテナにコピー
- HTMLファイルをデフォルトのNginxウェブルートにコピー
次に、基本的なnginx.confファイルを作成します:
touch nginx.conf
以下のシンプルな設定を追加します:
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
}
HTML ディレクトリを作成し、index.html ファイルを追加します:
mkdir html
echo "<h1>Hello from Nginx Docker!</h1>" > html/index.html
Docker イメージをビルドします:
docker build -t my-nginx-image .
コンテナを実行します:
docker run -d -p 8080:80 my-nginx-image
http://localhost:8080 にアクセスすると Hello from Nginx Docker! が表示されるかと思います。
Dockerイメージの環境変数を使用する
Nginx Docker イメージで環境変数を使用するには、envsubst
ユーティリティを使用します。このツールはNginxのイメージに既に含まれています。このアプローチにより、実行時にコンテナに渡された環境変数に基づいて動的な構成が可能になります。設定方法は以下の通りです:
まず、Nginx設定のテンプレートを作成します。nginx.conf
を nginx.conf.template
にリネームし、環境変数を使用するように変更します:
events {
worker_connections 1024;
}
http {
server {
listen ${PORT};
server_name ${SERVER_NAME};
location / {
root /usr/share/nginx/html;
index index.html;
}
}
}
スタートアップスクリプトを作成します。docker-entrypoint.sh
という名前のファイルを作成します。このスクリプトはテンプレート内の環境変数を置き換え、Nginxを起動します:
#!/bin/sh
envsubst < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
exec nginx -g 'daemon off;'
次に、Dockerfileを更新して、テンプレートとスタートアップスクリプトを使用するようにします:
FROM nginx:alpine
COPY nginx.conf.template /etc/nginx/nginx.conf.template
COPY docker-entrypoint.sh /
COPY ./html /usr/share/nginx/html
RUN chmod +x /docker-entrypoint.sh
CMD ["/docker-entrypoint.sh"]
更新されたDockerイメージをビルドします:
docker build -t my-nginx-env-image
環境変数を指定してコンテナを実行します:
docker run -d -p 8080:80 -e PORT=80 -e SERVER_NAME=example.com my-nginx-env-image
これで、Nginx設定は提供された環境変数の値を使用します。この設定により、イメージを再ビルドすることなくNginxの設定を変更することができます。
この方法を使用して他のNginx設定も変更できます。テンプレートに変数を追加し、コンテナ実行時に渡すだけです。更に、nginx.conf以外にも任意のファイルを生成することもできます。
このアプローチは、イメージをできるだけ汎用的で再利用可能に保ち、実行時に特定の構成を提供することが求められるコンテナ化環境で特に有用です。
まとめ
この投稿では、動的な環境変数をサポートするようにNginxのDockerイメージを構成する方法を探りました。以下はカバーした内容の概要です:
- 最初にNginxの概要を説明し、その強みと潜在的な使用例を議論しました。
- 静的コンテンツを提供するための基本的な Nginx Docker イメージを構築しました。
- その後、
envsubst
ユーティリティを使用して環境変数を使用した動的な構成をサポートするようにDockerイメージを拡張しました。
この設定を実装することで、開発環境から本番システムまで、さまざまなシナリオでnginxを簡単かつ効率的に展開できるようになります。
この方法は強力ですが、特に本番環境では環境変数を安全に管理することが重要です。Dockerシークレットやその他の安全な方法を使用して機密情報を扱うことを検討してください。
NginxのパフォーマンスとDockerの柔軟性の組み合わせにより、多くのWebサーバーのニーズに対応する堅牢な基盤が構築されます。これらの技術を自分の特定の使用例に最適に適応させ続けてください。
Docker化を楽しんでください!
参考文献
Eukaryaでは様々な職種で積極的にエンジニア採用を行っています!OSSにコントリビュートしていただける皆様からの応募をお待ちしております!
Eukarya is hiring for various positions! We are looking forward to your application from everyone who can contribute to OSS!
Eukaryaは、Re:Earthと呼ばれるWebGISのSaaSの開発運営・研究開発を行っています。Web上で3Dを含むGIS(地図アプリの公開、データ管理、データ変換等)に関するあらゆる業務を完結できることを目指しています。ソースコードはほとんどOSSとしてGitHubで公開されています。
➔ Eukarya Webサイト / ➔ note / ➔ GitHub
Eukarya is developing and operating a WebGIS SaaS called Re:Earth. We aim to complete all GIS-related tasks including 3D (such as publishing map applications, data management, and data conversion) on the web. Most of the source code is published on GitHub as OSS.
➔ Eukarya Official Page / ➔ Medium / ➔ GitHub