注記:DebianおよびAlpine Linux用のNGINX Plus Dockerfilesは、2022年12月に更新され、最新のNGINX Plusリリースおよびこれらのオペレーティングシステムディストリビューションのバージョンに対応するようになりました。これらのDockerfilesおよび命令では、NGINX Plusイメージの構築時にライセンス情報を渡すためにDockerシークレットを使用しています。
Dockerは、コンテナ(アプリケーションの実行に必要なすべてを含む、軽量でスタンドアロンの実行が可能なソフトウェアパッケージ)として分散アプリケーションを構築、出荷および実行するためのオープンプラットフォームです。コンテナは、Kubernetesなどのコンテナオーケストレーションプラットフォームによって導入およびオーケストレーションできます(このブログに記載されているDockerコンテナ技術の他に、NGINXは、NGINX Open SourceおよびNGINX PlusベースのバージョンでF5 NGINX Ingress Controllerを提供しています。NGINX Plusをご契約の方は、追加料金なしでサポートを利用可能です)。
ソフトウェアアプリケーションとして、NGINX Open SourceとF5 NGINX Plusは、Dockerを利用した優れたユースケースです。私たちは、DockerイメージのリポジトリであるDocker HubでNGINX Open Sourceイメージを公開しています。このブログでは、以下の方法について説明します。
- Docker Hubのイメージを使ってNGINX Open Sourceを導入する
- コンテナ内のNGINXを管理する(接続、設定、ログ、再読み込み、再起動する)
- 自作のDockerイメージを使ってNGINX Plusを導入する
はじめに
Dockerオープンプラットフォームには、コンテナを構築、実行、オーケストレーションするオープンソースのランタイムであるDocker Engineと、Docker化されたアプリケーションを開発コミュニティ全体、あるいは特定の組織内で配布、共有、コラボレーションするためのホストッデサービスであるDocker Hubが含まれています。
Dockerコンテナにより、開発者は、インフラストラクチャによる制約からアプリケーションを切り離し、アプリケーションの「コンテンツ」に集中できます。Docker化されたアプリケーションは、ラップトップ、ベアメタルサーバー、VM、クラウドなど、あらゆるインフラストラクチャに即座に移植でき、モジュール式コンポーネントとして、フル機能の分散アプリケーションに簡単に構成および再構成して、リアルタイムで継続的に革新できます。
Dockerについて詳しくは、DockerとはまたはDockerの完全なドキュメントをご覧ください。
NGINX Open SourceのDockerイメージの使用
Docker Hubで公開されているNGINX Open Sourceイメージを使用して、DockerコンテナでNGINXインスタンスを作成できます。
非常にシンプルな例から始めます。デフォルトのNGINX設定を使用してコンテナ内で動作するNGINXのインスタンスを起動するには、以下のコマンドを実行します。
# docker run --name mynginx1 -p 80:80 -d nginx
fcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580d
このコマンドは、NGINXイメージをベースにしたmynginx1という名前のコンテナを作成します。このコマンドは、ログファイルの名前に使用される長い形式のコンテナIDを返します。詳しくは、ログの管理を参照してください。
-p
オプションは、NGINXイメージによってコンテナで公開されるポート(ポート80)をDockerホストの指定ポートにマッピングするようにDockerに指示します。最初のパラメータはDockerホストのポートを指定し、2番目のパラメータはコンテナ内で公開されるポートにマッピングされます。
-d
オプションは、コンテナがデタッチドモードで実行されることを指定します。つまり、コンテナは、停止するまで動作し続けますが、コマンドラインで実行されるコマンドには反応しません。次のセクションでは、コンテナと対話する方法について説明します。
コンテナが作成および実行され、ポートがマッピングされていることを確認するために、docker
ps
を実行します(ここでは読みやすくするために出力を複数行に分けています)。
# docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
fcd1fb01b145 nginx:latest "nginx -g 'daemon of 16 seconds ago ...
... STATUS PORTS NAMES
... Up 15 seconds 0.0.0.0:80->80/tcp mynginx1
出力のPORTS
フィールドでは、Dockerホストのポート80がコンテナ内のポート80にマッピングされていることが示されています。NGINXが実行されていることを確認するもう1つの方法は、そのポートにHTTPリクエストを行うことです。これにより、デフォルトのNGINXのウェルカムページのコードが表示されます。
# curl http://localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully
installed and working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="https://www.nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
NGINX Dockerコンテナでの作業
これでNGINX Dockerコンテナが動作するようになりましたが、コンテンツとNGINX設定はどのように管理すればよいのでしょうか。また、ロギングについてはどうでしょうか。
SSHについての注意点
NGINXインスタンスへのSSHアクセスを有効にすることは一般的ですが、Dockerコンテナは一般的に単一の目的(この場合はNGINXの実行)に使用されることから、NGINXイメージにOpenSSHはインストールされていません。そのため、代わりに、Dockerでサポートされている他の方法を使います。
この後のコンテンツと設定ファイルの管理で説明するコマンドの代わりとして、以下のコマンドを実行すると、実行中のNGINXコンテナに対して(SSHセッションを開始する代わりに)インタラクティブシェルを開くことができます。ただし、この方法は上級ユーザーのみにお勧めします。
-
Alpine Linuxシステムの場合:
# docker exec -it <NGINX_container_ID> sh
-
Debianシステムの場合:
# docker exec -it <NGINX_container_ID> bash
コンテンツと設定ファイルの管理
NGINXが公開するコンテンツとNGINX設定ファイルの両方を管理する方法はいくつかあります。ここでは、そのうちのいくつかの方法について説明します。
オプション1:Dockerホスト上でコンテンツと設定を維持する
コンテナを作成するときに、Dockerホスト上のローカルディレクトリをコンテナ内のディレクトリにマウントするようにDockerに指示できます。NGINXイメージは、デフォルトのNGINX設定を使用して、/usr/share/nginx/htmlをコンテナのルートディレクトリとして使用し、/etc/nginxに設定ファイルを保存しています。Dockerホスト上のローカルディレクトリ/var/wwwにコンテンツがあり、 /var/nginx/confに設定ファイルがある場合、以下のコマンドを実行します(ここでは読みやすくするために出力を複数行に分けています)。
# docker run --name mynginx2 --mount type=bind source=/var/www,target=/usr/share/nginx/html,readonly --mount type=bind,source=/var/nginx/conf,target=/etc/nginx/conf,readonly -p 80:80 -d nginx
これで、Dockerホスト上のローカルディレクトリ/var/wwwと/var/nginx/confにあるファイルへのすべての変更は、コンテナにあるディレクトリ/usr/share/nginx/htmlと/etc/nginxに反映されるようになりました。readonly
オプションを使用すると、これらのディレクトリの変更がコンテナ内からではなく、Dockerホスト上のみで許可されます。
オプション2: Dockerホストからファイルをコピーする
もう1つのオプションは、コンテナ作成時にDockerホスト上のローカルディレクトリからコンテンツと設定ファイルをDockerにコピーさせる方法です。この方法では、コンテナが作成されていると、ファイル変更時に新しいコンテナを作成するか、コンテナ内のファイルを変更することでファイルが維持されます。ファイルをコピーする簡単な方法は、Dockerfileを作成して、そこにDocker HubからNGINXイメージをベースにした新しいDockerイメージを生成するときに実行されるコマンドを追加することです。Dockerfileのファイルコピー(COPY
)コマンドでは、ローカルディレクトリのパスは、Dockerfileが置かれているビルドコンテキストからの相対パスです。
この例では、コンテンツはcontentディレクトリに、設定ファイルはconfディレクトリにあり、いずれもDockerfileが置かれているディレクトリのサブディレクトリです。NGINXイメージには、/etc/nginx/nginx.confおよび/etc/nginx/conf.d/default.confという名前のデフォルトのNGINX設定ファイルが含まれています。ここでは、ホストの設定ファイルを使用したいので、デフォルトファイルを削除するRUN
コマンドを含めます。
FROM nginx
RUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx
Dockerfileが置かれているディレクトリから以下のコマンドを実行して、独自のNGINXイメージを作成します。コマンドの最後にピリオド(「.」)があることに注意してください。これにより、カレントディレクトリが、Dockerfileとコピーされるディレクトリを含むビルドコンテキストとして定義されます。
# docker build -t mynginx_image1 .
ここで、以下のコマンドを実行して、mynginx_image1イメージをベースにしたmynginx3というコンテナを作成します。
# docker run --name mynginx3 -p 80:80 -d mynginx_image1
コンテナ内のファイルを変更する場合、オプション3で説明するヘルパーコンテナを使用します。
オプション3:コンテナ内のファイルを維持する
前述のSSHについての注意点で説明したように、SSHを使用してNGINXコンテナにアクセスすることはできないため、コンテンツや設定ファイルを直接編集する場合、シェルアクセスが可能なヘルパーコンテナを作成する必要があります。ヘルパーコンテナがファイルにアクセスできるようにするには、このイメージ用の適切なDockerデータボリュームが定義された新しいイメージを作成する必要があります。ボリュームを定義した状態で、オプション2の方法でファイルをコピーする場合、以下のDockerfileを使用します。
FROM nginx
RUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx
VOLUME /usr/share/nginx/html
VOLUME /etc/nginx
次に、以下のコマンドを実行して新しいNGINXイメージを作成します(ここでも、最後のピリオドに注意してください)。
# docker build -t mynginx_image2 .
ここで、以下のコマンドを実行して、mynginx_image2イメージをベースにしたmynginx4というNGINXコンテナを作成します。
# docker run --name mynginx4 -p 80:80 -d mynginx_image2
次に、以下のコマンドを実行して、シェルを持つヘルパーコンテナmynginx4_filesを起動します。これにより、上記で作成したmynginx4コンテナのコンテンツと設定ディレクトリにアクセスできます。
# docker run -i -t --volumes-from mynginx4 --name mynginx4_files debian /bin/bash
root@b1cbbad63dd1:/#
新しいmynginx4_filesヘルパーコンテナは、永続的な標準入力(-i
オプション)およびtty(-t
オプション)を使用してフォアグラウンドで実行されます。mynginx4で定義されたすべてのボリュームは、ヘルパーコンテナのローカルディレクトリとしてマウントされます。
debian
引数を使用すると、ヘルパーコンテナはDocker HubのDebianイメージを使用します。NGINXイメージもDebianを使用しているので(さらに、これまでの例ではすべてこのNGINXイメージを使用しているので)、Dockerに別のオペレーティングシステムをロードさせるよりも、ヘルパーコンテナにDebianを使用することが最も効率的です。
/bin/bash
引数を使用すると、bash
シェルがヘルパーコンテナで実行され、必要に応じてファイルを変更するためのシェルプロンプトが表示されます。
コンテナを起動および停止するには、以下のコマンドを実行します。
# docker start mynginx4_files
# docker stop mynginx4_files
シェルを終了してコンテナを実行したままにするには、Ctrl+p
を押した後にCtrl+q
を押します。実行中のコンテナへのシェルアクセスを回復するには、以下のコマンドを実行します。
# docker attach mynginx4_files
シェルを終了してコンテナを終了するには、exit
コマンドを実行します。
ログの管理
デフォルトのログまたはカスタマイズしたログを設定できます。
デフォルトのログの使用
NGINXイメージは、デフォルトでは、メインのNGINXアクセスログとエラーログがDockerログコレクタに送信されるように設定されています。それぞれのログは、stdout
とstderr
にリンクされています。これら両方のログからのすべてのメッセージは、Dockerホストの/var/lib/docker/containers/<container_ID>/<container_ID>-json.logファイルに書き込まれます。ここで、<container_ID>は、コンテナ作成時に返される長い形式のIDです。たとえば、NGINX Open SourceのDockerイメージの使用You can use also the Docker Engine API で作成した最初のコンテナの場合、fcd1fb01b14557c7c9d991238f2558ae2704d129cf9fb97bb4fadf673a58580dです。
既存コンテナのコンテナIDを取得するには、以下のコマンドを実行します。ここで、 <container_name>
は、コンテナ作成時に--name
パラメータによって設定された値です(たとえば、上記のコンテナIDの場合、mynginx1です)。
# docker inspect --format '{{ .Id }}' <container_name>
<container_ID>-json.logファイルを直接開くことでログを表示できますが、通常、以下のコマンドを実行する方が簡単です。
# docker logs <container_name>
Docker Unixソケットに対してGET
リクエストを発行することにより、Docker Engine APIを使用してログメッセージを抽出することもできます。以下のコマンドは、アクセスログ(stdout=1
と指定)とエラーログ(stderr=1
と指定)の両方を返しますが、それぞれ単独で要求することもできます。
# curl --unix-socket /var/run/docker-sock http://localhost/containers/<container_name>/logs?stdout=1&stderr=1
その他のクエリーパラメータについては、Docker Engine APIのドキュメントをご覧ください(ページ内で「コンテナログの取得」を検索してください)。
カスタマイズしたログの使用
別の方法でログを収集する場合、または特定の設定ブロック(server{}
やlocation{}
など)で別のログを設定する場合、ログファイルを保存するコンテナ内の1つ以上のディレクトリのためのDockerボリュームを定義し、ログファイルにアクセスするヘルパーコンテナを作成して、任意のログツールを使用できます。このように実装するには、ログファイル用の1つ以上のボリュームが含まれる新しいイメージを作成します。
たとえば、ログファイルが/var/log/nginx/logに保存されるようにNGINXを設定するには、オプション3で説明したDockerfileを使用して、このディレクトリのVOLUME
定義を追加するだけです。
FROM nginx
RUN rm /etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY content /usr/share/nginx/html
COPY conf /etc/nginx
VOLUME /var/log/nginx/log
次に、上記で説明したようにイメージを作成し、そのイメージを使用して、NGINXコンテナとログ用のディレクトリにアクセスできるヘルパーコンテナを作成できます。このヘルパーコンテナには、任意のログツールをインストールできます。
NGINXの制御
NGINXコンテナのコマンドラインに直接アクセスすることはできないので、nginx
コマンドを使用してNGINXを制御することはできません。代わりに、シグナルを使用してNGINXを制御できます。Dockerはコンテナにシグナルを送信するためのkill
コマンドを提供しています。
NGINXの設定を再読み込みするには、以下のコマンドを実行します。
# docker kill -s HUP <container_name>
NGINXを再起動するには、以下のコマンドを実行してコンテナを再起動します。
# docker restart <container_name>
Dockerを使用したNGINX Plusの導入
ここまで、NGINX Open SourceでDockerを使用する方法について説明してきました。しかし、Dockerは、商用版のNGINX Plusでも使用できます。これらの違いは、商用版のNGINX PlusはDocker Hubでは利用できないため、最初にNGINX Plusのイメージを作成する必要があることです。幸い、NGINX Plusのイメージは非常に簡単に作成できます。
注:NGINX PlusイメージをDocker Hubのようなパブリックリポジトリにアップロードしないでください。このような行為は、ライセンス契約違反となります。
NGINX PlusのDockerイメージの作成
NGINX Plusのイメージを生成するには、最初にDockerfileを作成します。ここで説明する例では、ベースのDockerイメージとしてDebian 11 (Bullseye)およびAlpine Linux 3.17を使用します。NGINX PlusのDockerイメージを作成する前に、お使いのバージョンのnginx-repo.crtおよびnginx-repo.keyファイルをダウンロードする必要があります。これらのファイルは、NGINX Plusをご契約の方は、カスタマポータルからダウンロードできます。NGINX Plusの無料トライアル版を利用されている方は、トライアルパッケージと一緒に提供されています。ファイルは、Dockerfileが置かれているディレクトリ(Dockerビルドコンテキスト)にコピーしてください。
NGINX Open Sourceと同様、デフォルトでは、NGINX PlusのアクセスログとエラーログはDockerログコレクタにリンクされています。ボリュームは指定されていませんが、必要な場合、ボリュームを追加できます。また、各Dockerfileを使用してベースイメージを作成し、そのイメージから前述のようにボリュームを指定して新しいイメージを作成することもできます。
NGINX Plusの新しいリリースにアップデートしたときにファイルを編集しなくて済むように、このサンプルのDockerfilesでは、意図的にNGINX Plusのバージョンを指定していません。ただし、関連する手順にバージョンをコメントとして追加していますので、ファイルバージョンを指定する場合にはコメントを解除してください。
同じように、NGINX Plusの正式な動的モジュールをインストールするための手順も(コメントとして)追加しています。
デフォルトでは、コンテナの作成時にDockerホストからコピーされるファイルはありません。各DockerfileにCOPY
定義を追加するか、作成したイメージを上記で説明したように別のイメージのベースとして使用できます。
NGINX Plus Dockerfile (Debian 11)
NGINX Plus Dockerfile (Alpine Linux 3.17)
NGINX Plusのイメージの作成
Dockerfile、nginx-repo.crtおよびnginx-repo.keyファイルを同じディレクトリに置き、以下のコマンドを実行して、nginxplusという名前のDockerイメージを作成します(先ほどと同じように、最後のピリオドに注意してください)。
# DOCKER_BUILDKIT=1 docker build --no-cache -t nginxplus --secret id=nginx-crt,src=</path/to/your/nginx-repo.crt> --secret id=nginx-key,src=</path/to/your/nginx-repo.key> .
DOCKER_BUILDKIT=1
フラグは、Docker BuildKitを使用してイメージを構築していることを示します。これは、後述の--secret
オプションを含めるときに必要となります。
--no-cache
オプションを使用すると、Dockerはイメージを最初から構築し、NGINX Plusの最新バージョンが必ずインストールされます。以前にDockerfileを使用してイメージを構築していて、--no-cache
オプションを指定しなかった場合、新しいイメージでは、DockerキャッシュにあるNGINX Plusのバージョンが使用されます(前述のように、NGINX Plusの新しいリリースにアップデートするたびにファイルを変更しなくて済むように、このDockerfileでは、意図的にNGINX Plusのバージョンを指定していません)。以前に構築したイメージのNGINX Plusバージョンをそのまま使用する場合、--no-cache
オプションを省略してください。
--secret
オプションを使用すると、データが漏洩する、あるいはDockerビルド層間でデータが永続化するリスクなく、NGINX Plusライセンスの証明書と鍵がDockerビルドコンテキストに渡されます。id
引数の値は、ベースのDockerfileを変更しない限り変更できませんが、src
引数は、NGINX Plusの証明書と鍵のファイルへのパス(前述の指示に従っている場合はDockerイメージを構築しているのと同じディレクトリ)に設定する必要があります。
docker
images
nginxplus
コマンドから以下のような出力が返されると、イメージは正常に作成されています。
# docker images nginxplus
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
nginxplus latest ef2bf65931cf 6 seconds ago 91.2 MB
このイメージをベースにして、mynginxplusという名前のコンテナを作成するには、以下のコマンドを実行します。
# docker run --name mynginxplus -p 80:80 -d nginxplus
NGINX Plusコンテナは、NGINXコンテナと同じように制御および管理できます。
まとめ
NGINX、NGINX Plus、Dockerは、非常にスムーズに連携します。Docker HubからNGINX Open Sourceのイメージを使用する場合でも、独自のNGINX Plusのイメージを作成する場合でも、NGINXとNGINX Plusの新しいインスタンスをDockerコンテナで簡単に起動し、Kubernetes環境に導入できます。また、ベースのイメージから新しいDockerイメージを簡単に作成できるので、コンテナの制御や管理がさらに簡単になります。Dockerコンテナで実行しているすべてのNGINX Plusインスタンスが、ご自身の契約範囲内であることを確認してください。詳しくは、NGINX営業チームにお問い合わせください。