注記 -このブログは、 2020年5月時点での更新となります。この時点でのDockerコマンドに準拠し、DebianおよびAlpine Linuxディストリビューション用NGINX Plusの Dockerfileを提供しています。
Dockerは、コンテナ(軽量でスタンドアロンで実行が可能なソフトウェアパッケージであり、アプリケーションを実行するために必要なものをすべてが含んで動作する)とよばれる形式で分散型アプリケーションを構築、デプロイ、実行するためのオープンなプラットフォームです。コンテナは、Kubernetesなどのコンテナオーケストレーションプラットフォームによってデプロイや横断的な管理を行うことが可能です(このブログで取り上げたDockerコンテナの他に、 NGINXはNGINX Open SourceとNGINX Plus Ingress Controllers for Kubernetesを提供しています。NGINX Plusご利用の方は、追加料金なしでサポートを利用いただけます)。
ソフトウェアアプリケーションの観点において、NGINX Open SourceとNGINX Plusは、Dockerを利用した優れたユースケースであり、NGINXはDockerイメージのリポジトリであるDocker HubにNGINX Open Source イメージを公開しています。このブログでは、Docker Hubのイメージを使用して、NGINX Open Sourceをデプロイする方法と、お客様環境でご利用いただくためのNGINX PlusのDockerイメージを作成と作成舌イメージをプロイする方法について説明します。
はじめに
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 STATUS ...
fcd1fb01b145 nginx:latest "nginx -g 'daemon of 16 seconds ago Up 15 seconds ...
... PORTS NAMES
... 0.0.0.0:80->80/tcp mynginx1
出力にあるPORTS
フィールドは、Dockerホストのポート80がコンテナ内のポート80にマッピングされていることを示しています。NGINXが実行していることを確認するもう一つの方法は、そのポートに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セッションを起動する代わりに)インタラクティブシェルを開くことができます。ただし、この方法は、上級ユーザーにのみ推奨されます。
-
Debianシステムの場合:
# docker exec -it NGINX_container_ID bash
-
Alpine Linuxシステムの場合:
# docker exec -it NGINX_container_ID sh
コンテンツと構成ファイルの管理
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ホストのローカルディレクトリからコンテンツと構成ファイルをコピーさせる方法です。コンテナが一度作成されると、ファイルが変更されたときに新しいコンテナを作成するか、コンテナ内のファイルを変更したりすることでファイルの管理がなされます。ファイルをコピーする簡単な方法は、Docker Hubの新しい NGINXイメージをベースにしたDockerイメージを生成するときに、Dockerfile。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+p
を押します。実行中のコンテナでシェルをもう一度使用するには、次のコマンドを実行します。
# docker attach mynginx4_files
シェルを終了してコンテナを終了するには、exit
コマンドを実行します。
ログの管理
デフォルトまたはカスタマイズしたログを構成できます。
デフォルトのログの使用
NGINXイメージは、デフォルトで、メインのNGINXアクセスログとエラーログをDockerログコレクタに送信するように構成されています。これは、stdout
とstderr
に紐付けられており、両方のログのすべてのメッセージは、Dockerホスト上のファイル /var/lib/docker/containers/container-ID/container-ID-json.logに書き込まれます。例えば、前述の「NGINXオープンソースDockerイメージの使用」で作成した最初のコンテナは次の通りでした。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
で表される)とエラーログ(code>stderr=1)の両方を返しますが、単独で要求することもできます。
curl --unix-socket /var/run/docker-sock http://localhost/containers/container-name/logs?stdout=1&stderr=1
その他のクエリパラメータについては、Docker Engine APIのドキュメントをご覧ください(ページ内で「Get container logs」を検索してください)。
カスタマイズしたログの使用
ログを収集する際に別の方法を実装する場合や、特定の構成ブロック(server{}やlocation{}など)で別のログの設定を行う場合は、コンテナ内でログファイルを保存するディレクトリのためにDockerボリュームを定義し、ログファイルにアクセスするヘルパーコンテナを作成することで、希望するlogツールを自由に使用できます。これを実装するには、ログファイル用のボリューム(複数可)が含まれる新しいイメージを作成してください。
たとえば、ログファイルを/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コンテナとして使用する方法について説明してきましたが、商用版のNGINX PlusでもDockerを利用できます。商用版とオープンソースの違いは、商用版のNGINX PlusはDocker Hubでは利用できないため、最初にNGINX Plusのイメージを作成する必要があることです。NGINX Plusのイメージはとても簡単に作成できます。
注:NGINX PlusイメージをDocker Hubのようなパブリックリポジトリにアップロードしないでください。このような行為は、ライセンス契約違反となります。
NGINX PlusのDockerイメージの作成
NGINX Plusのイメージを生成するには、最初にDockerfileを作成します。ここで説明する例では、ベースのDockerイメージとしてDebian 10(Buster)Alpine Linux 3.11を使用しています。NGINX PlusのDockerイメージを作成する前に、お使いのバージョンのnginx-repo.crtとnginx-repo.keyファイルをダウンロードする必要があります。NGINX Plusのお客様は、カスタマーポータル(MyF5)からダウンロードできます。NGINX Plusの無料トライアルを利用されている場合は、これらのファイルはトライアルパッケージと一緒に提供されます。Dockerfileがあるディレクトリ(Dockerビルドコンテキスト)にファイルをコピーします。
NGINX Open Sourceと同じように、デフォルトでは、NGINX PlusのアクセスログとエラーログはDockerログコレクタにリンクされます。ボリュームは指定されていませんが、必要に応じてボリュームを追加することができます。また、各Dockerfileを使用してベースイメージを作成し、そのイメージから前述のようにボリュームを指定して新しいイメージを作成することもできます。
NGINX Plusの新しいリリースにアップデートしたときにファイルを編集する必要がないよう、このサンプルのDockerfileでは、意図的にNGINX Plusのバージョンを指定していません。ただし、関連する手順にバージョンをコメントとして追加していますので、ファイルバージョンを指定する場合にはコメントを外してください。
同じように、NGINX Plusの正式な動的モジュールをインストールするための手順も追加(コメントアウト)しています。
デフォルトでは、コンテナの作成時にDockerホストからコピーされるファイルはありません。各DockerfileにCOPY
定義を追加することができます。また、作成したイメージを上記で説明したように別のイメージのベースとして使用することもできます。
NGINX Plus Dockerfile(Debian 10)
NGINX Plus Dockerfile(Alpine Linux 3.11)
NGINX Plusのイメージの作成
Dockerfile、nginx-repo.crt、nginx-repo.keyファイルを同じディレクトリに保存して、次のコマンドを実行し、nginxplusという名前のDockerイメージを作成します(先ほどと同じように、最後のピリオドに注意してください)。
# docker build --no-cache -t nginxplus .
--no-cache
optionオプションを使用すると、Dockerはイメージをスクラッチから構築し、NGINX Plusの最新バージョンが必ずインストールされます。以前にイメージを構築するのにDockerfileを使用しており、--no-cache
optionオプションを指定しなかった場合、新しいイメージでは、DockerキャッシュにあるNGINX Plusのバージョンを使用します(NGINX Plusの新バージョンがリリースされるたびにファイルを変更する必要がないように、Dockerfileでは意図的にバージョンを指定していません)。前に構築したイメージのNGINX Plusバージョンをそのまま使用される場合は、--no-cache
optionオプションを省略してください。
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インスタンスが、サブスクリプションの範囲内であることを確認してください。さらなる詳細のご希望、ご質問等ございましたら、お問合せフォームよりご連絡ください。