前書き

https://nodejs.org [Node.js]アプリケーションの柔軟性とセキュリティを強化する方法は複数あります。 reverse proxy(https://www.nginx.com/[Nginx]など)を使用すると、負荷を分散することができます。リクエスト、静的コンテンツのキャッシュ、Transport Layer Security(TLS)の実装。 サーバーで暗号化されたHTTPSを有効にすると、アプリケーションとの通信が安全に保たれます。

コンテナにTLS / SSLを使用してリバースプロキシを実装するには、ホストオペレーティングシステムで直接作業する場合とは異なる一連の手順が必要です。 たとえば、サーバーで実行されているアプリケーションの証明書をhttps://letsencrypt.org/[Let’s Encrypt]から取得している場合、必要なソフトウェアをホストに直接インストールします。 コンテナを使用すると、異なるアプローチを取ることができます。 Docker Composeを使用して、アプリケーション、Webサーバー、およびhttps://certbot.eff.org/[Certbot client]のコンテナを作成して、それを有効にすることができます証明書を取得します。 これらの手順に従うことで、コンテナ化されたワークフローのモジュール性と移植性を活用できます。

このチュートリアルでは、Docker Composeを使用して、Nginxリバースプロキシを使用してNode.jsアプリケーションをデプロイします。 アプリケーションに関連付けられたドメインのTLS / SSL証明書を取得し、https://www.ssllabs.com/ [SSL Labs]から高いセキュリティ評価を受けることを確認します。 最後に、https://www.digitalocean.com/community/tutorials/how-to-schedule-routine-tasks-with-cron-and-anacron-on-a-vps [+ cron +]を設定しますドメインを安全に保つために証明書を更新する仕事。

前提条件

このチュートリアルを実行するには、次のものが必要です。

  • Ubuntu 18.04サーバー、 `+ sudo +`特権を持つ非rootユーザー、およびアクティブなファイアウォール。 これらの設定方法に関するガイダンスについては、https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-18-04 [初期サーバー設定ガイド]をご覧ください。

  • サーバーにインストールされたDockerおよびDocker Compose。 Dockerのインストールに関するガイダンスについては、https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-18-04のステップ1および2を参照してください。 Ubuntu 18.04でDockerを使用してください]。 Composeのインストールに関するガイダンスについては、https://www.digitalocean.com/community/tutorials/how-to-install-docker-compose-on-ubuntu-18-04のステップ1に従ってください[Ubuntu 18.04にDocker Composeをインストールする方法] ]。

  • 登録済みのドメイン名。 このチュートリアルでは、全体を通して* example.com *を使用します。 Freenomから無料で入手するか、選択したドメインレジストラーを使用できます。

  • 次の両方のDNSレコードがサーバーに設定されています。 DigitalOceanアカウントに追加する方法の詳細については、https://www.digitalocean.com/community/tutorials/an-introduction-to-digitalocean-dns [このDigitalOcean DNSの概要]を参照してください。再使用:

  • サーバーのパブリックIPアドレスを指す「++」を持つAレコード。

  • サーバーのパブリックIPアドレスを指す「+ www。+」を持つAレコード。

手順1-ノードアプリケーションの複製とテスト

最初のステップとして、Composeを使用してアプリケーションイメージをビルドするために使用するDockerfileを含むNodeアプリケーションコードを使用して、リポジトリのクローンを作成します。 `+docker run + `commandを使用して、リバースプロキシやSSLを使用せずにアプリケーションをビルドして実行することで、最初にアプリケーションをテストできます。

非ルートユーザーのホームディレクトリで、https://github.com/doからhttps://github.com/do-community/nodejs-image-demo [`+ nodejs-image-demo +`リポジトリ]を複製します。 -community [DigitalOcean Community GitHubアカウント]。 このリポジトリには、https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with-docker [Node.jsアプリケーションの構築方法]で説明されているセットアップのコードが含まれています。 Docker]。

リポジトリを `++`というディレクトリにクローンします:

git clone https://github.com/do-community/nodejs-image-demo.git

`++`ディレクトリに移動します。

cd

このディレクトリには、https://hub.docker.com/_/node/ [Docker + node:10 + image]と現在のプロジェクトのコンテンツを使用してNodeアプリケーションを構築するための手順を含むDockerfileがありますディレクトリ。 次のように入力して、Dockerfileの内容を確認できます。

cat Dockerfile
OutputFROM node:10-alpine

RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app

WORKDIR /home/node/app

COPY package*.json ./

USER node

RUN npm install

COPY --chown=node:node . .

EXPOSE 8080

CMD [ "node", "app.js" ]

これらの手順は、プロジェクトコードを現在のディレクトリからコンテナにコピーし、 + npm install +`で依存関係をインストールすることにより、ノードイメージを構築します。 また、 `+ packageのコピーを分離することにより、Dockerのhttps://www.digitalocean.com/community/tutorials/building-optimized-containers-for-kubernetes#managing-container-layers [キャッシュとイメージレイヤー]を利用します。 json + `および + package-lock.json + `。残りのアプリケーションコードのコピーから、プロジェクトのリストされた依存関係を含みます。 最後に、手順は、アプリケーションコードと `+ node_modules +`ディレクトリに適切な権限が設定された非ルート* node *ユーザーとしてコンテナが実行されることを指定します。

このDockerfileおよびNodeイメージのベストプラクティスの詳細については、https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with-docker#の完全な説明を参照してください。 step-3-%E2%80%94-writing-the-dockerfile [DockerでNode.jsアプリケーションを構築する方法のステップ3]。

SSLを使用せずにアプリケーションをテストするには、https://docs.docker.com/engine/reference/commandline/build/ [+ docker build +]および `+ -t `フラグを使用してイメージをビルドおよびタグ付けできます。 画像を「+」と呼びますが、別の名前を自由に付けることができます。

docker build -t  .

ビルドプロセスが完了すると、https://docs.docker.com/engine/reference/commandline/images/ [+ docker images +]で画像を一覧表示できます。

docker images

次の出力が表示され、アプリケーションイメージのビルドが確認されます。

OutputREPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
          latest              23961524051d        7 seconds ago       73MB
node                10-alpine           8a752d5af4ce        3 weeks ago         70.7MB

次に、 `+ docker run`でコンテナを作成します。 このコマンドには3つのフラグが含まれます。

  • + -p +:これはコンテナ上のポートを公開し、ホスト上のポートにマッピングします。 ホストではポート「80」を使用しますが、そのポートで別のプロセスを実行している場合は、必要に応じて自由に変更してください。 これがどのように機能するかについての詳細は、https://docs.docker.com/v17.09/engine/userguide/networking/default_network/binding/ [ポートバインディング]のDockerドキュメントのこの説明を参照してください。

  • + -d +:これはバックグラウンドでコンテナを実行します。

  • +-name +:これにより、コンテナに覚えやすい名前を付けることができます。

次のコマンドを実行して、コンテナを構築します。

docker run --name  -p 80:8080 -d

`+docker ps + `で実行中のコンテナを検査します。

docker ps

アプリケーションコンテナが実行されていることを確認する出力が表示されます。

OutputCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
4133b72391da                   "node app.js"       17 seconds ago      Up 16 seconds       0.0.0.0:80->8080/tcp

ドメインにアクセスして、セットアップをテストできます: + http:// +。 `++`を自分のドメイン名に置き換えることを忘れないでください。 アプリケーションには、次のランディングページが表示されます。

image:https://assets.digitalocean.com/articles/docker_node_image/landing_page.png [アプリケーションのランディングページ]

アプリケーションをテストしたので、コンテナーを停止してイメージを削除できます。 もう一度 `+ docker ps `を使用して、 ` CONTAINER ID +`を取得します。

docker ps
OutputCONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                  NAMES
                  "node app.js"       17 seconds ago      Up 16 seconds       0.0.0.0:80->8080/tcp

https://docs.docker.com/engine/reference/commandline/stop/[`docker stop + `]でコンテナを停止します。 ここにリストされている ` CONTAINER ID `を独自のアプリケーション ` CONTAINER ID +`に置き換えてください:

docker stop

+docker system prune + `および + -a + `フラグ:

docker system prune -a

出力でプロンプトが表示されたら、「+ y +」と入力して、停止したコンテナとイメージを削除することを確認します。 これによりビルドキャッシュも削除されることに注意してください。

アプリケーションイメージをテストしたら、Docker Composeを使用して残りのセットアップの構築に進むことができます。

ステップ2-Webサーバー構成の定義

アプリケーションDockerfileを配置したら、Nginxコンテナーを実行するための構成ファイルを作成できます。 ドメイン名https://docs.nginx.com/nginx/admin-guide/web-server/serving-static-content/#root-directory-and-index-filesを含む最小限の構成から始めます。 [ドキュメントルート]、プロキシ情報、およびロケーションブロック。Certbotのリクエストを `+ .well-known +`ディレクトリに転送します。このディレクトリでは、ドメインのDNSがサーバーに解決されることを検証する一時ファイルを配置します。

まず、現在のプロジェクトディレクトリに構成ファイル用のディレクトリを作成します。

mkdir nginx-conf

`+ nano +`またはお気に入りのエディターでファイルを開きます:

nano nginx-conf/nginx.conf

Nodeアプリケーションコンテナへのユーザーリクエストをプロキシし、Certbotのリクエストを `+ .well-known `ディレクトリに転送するために、次のサーバーブロックを追加します。 必ず `+`を自分のドメイン名に置き換えてください:

〜/ node_project / nginx-conf / nginx.conf

server {
       listen 80;
       listen [::]:80;

       root /var/www/html;
       index index.html index.htm index.nginx-debian.html;

       server_name  www.;

       location / {
               proxy_pass http://nodejs:8080;
       }

       location ~ /.well-known/acme-challenge {
               allow all;
               root /var/www/html;
       }
}

このサーバーブロックにより、Nginxコンテナーをリバースプロキシとして起動し、Nodeアプリケーションコンテナーにリクエストを渡すことができます。 また、Certbotのhttps://certbot.eff.org/docs/using.html#webroot[webroot plugin]を使用してドメインの証明書を取得することもできます。 このプラグインはhttps://tools.ietf.org/html/draft-ietf-acme-acme-03#section-7.2[HTTP-01検証方法]に依存します。これはHTTP要求を使用して、Certbotがリソースにアクセスできることを証明します特定のドメイン名に応答するサーバーから。

編集が完了したら、ファイルを保存して閉じます。 Nginxサーバーとロケーションブロックアルゴリズムの詳細については、https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms [Nginxサーバーについて]のこの記事を参照してください。およびロケーションブロック選択アルゴリズム]。

Webサーバー設定の詳細が整ったら、 `+ docker-compose.yml +`ファイルの作成に移ります。これにより、証明書の取得に使用するアプリケーションサービスとCertbotコンテナーを作成できます。

ステップ3-Docker Composeファイルの作成

`+ docker-compose.yml +`ファイルは、NodeアプリケーションやWebサーバーなどのサービスを定義します。 名前付きボリュームなどの詳細を指定します。これは、コンテナー間でSSL資格情報を共有するために重要であり、ネットワークおよびポート情報も同様です。 また、コンテナの作成時に実行する特定のコマンドを指定できます。 このファイルは、サービスの連携方法を定義する中心的なリソースです。

現在のディレクトリでファイルを開きます。

nano docker-compose.yml

最初に、アプリケーションサービスを定義します。

〜/ node_project / docker-compose.yml

version: '3'

services:
 nodejs:
   build:
     context: .
     dockerfile: Dockerfile
   image: nodejs
   container_name: nodejs
   restart: unless-stopped

`+ nodejs +`サービス定義には以下が含まれます:

  • + build +:これは、Composeがアプリケーションイメージをビルドするときに適用される、 + context`や + dockerfile`などの構成オプションを定義します。 Docker Hubなどのレジストリの既存のイメージを使用する場合は、https://docs.docker.com/compose/compose-file/#image [代わりに、ユーザー名、リポジトリ、画像タグに関する情報を含む「+ image + `命令」。

  • + context +:アプリケーションイメージビルドのビルドコンテキストを定義します。 この場合、それは現在のプロジェクトディレクトリです。

  • + dockerfile +:これは、Composeがビルドに使用するDockerfileを指定します-https://www.digitalocean.com/community/tutorials/how-to-secure-a-containerized-node-jsで見たDockerfile -application-with-nginx-let-s-encrypt-and-docker-compose#step-1-%E2%80%94-cloning-and-testing-the-node-application [ステップ1]。

  • + image ++ container_name +:これらは画像とコンテナに名前を適用します。

  • + restart +:これは再起動ポリシーを定義します。 デフォルトは「+ no +」ですが、停止しない限りコンテナを再起動するように設定しています。

私たちのセットアップは開発ではなく展開に焦点を合わせているため、このサービスにはバインドマウントが含まれていないことに注意してください。 詳細については、https://docs.docker.com/storage/bind-mounts/ [bind mounts]およびhttps://docs.docker.com/storage/volumes/[volumes]のDockerドキュメントを参照してください。

アプリケーションとWebサーバーコンテナ間の通信を有効にするために、再起動定義の下に「+ app-network +」というブリッジネットワークも追加します。

〜/ node_project / docker-compose.yml

services:
 nodejs:
...

このようなユーザー定義のブリッジネットワークにより、同じDockerデーモンホスト上のコンテナー間の通信が可能になります。 これにより、アプリケーション内のトラフィックと通信が合理化されます。同じブリッジネットワーク上のコンテナ間のすべてのポートが開かれ、ポートが外部に公開されないためです。 したがって、フロントエンドサービスを公開するために必要なポートのみを開くことを選択できます。

次に、 `+ webserver +`サービスを定義します:

〜/ node_project / docker-compose.yml

...
webserver:
   image: nginx:
   container_name: webserver
   restart: unless-stopped
   ports:
     - "80:80"
   volumes:
     - web-root:/var/www/html
     - ./nginx-conf:/etc/nginx/conf.d
     - certbot-etc:/etc/letsencrypt
     - certbot-var:/var/lib/letsencrypt
   depends_on:
     - nodejs
   networks:
     - app-network

`+ nodejs +`サービス用に定義した設定の一部は同じままですが、次の変更も加えました:

  • + image +:これにより、ComposeはDocker Hubから最新のhttps://alpinelinux.org/[Alpine-based] Nginx imageをプルするように指示されます。 「+ alpine +」画像の詳細については、https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with-docker#step-3のステップ3を参照してください-%E2%80%94-writing-the-dockerfile [DockerでNode.jsアプリケーションをビルドする方法]。

  • + ports +:これは、ポート `+ 80 +`を公開して、Nginx設定で定義した設定オプションを有効にします。

次の名前付きボリュームとバインドマウントも指定しました。

  • + web-root:/ var / www / html:これにより、` + web-root + というボリュームにコピーされたサイトの静的アセットが、コンテナの + / var / www / html`ディレクトリに追加されます。

  • +。/ nginx-conf:/ etc / nginx / conf.d +:これにより、ホスト上のNginx設定ディレクトリがコンテナ上の関連ディレクトリにバインドマウントされ、ホスト上のファイルに加えた変更が確実に行われます。コンテナに反映されます。

  • + certbot-etc:/ etc / letsencrypt +:これにより、ドメインの関連するLet’s Encrypt証明書とキーがコンテナの適切なディレクトリにマウントされます。

  • + certbot-var:/ var / lib / letsencrypt +:これにより、Let’s Encryptのデフォルトの作業ディレクトリがコンテナの適切なディレクトリにマウントされます。

次に、 `+ certbot +`コンテナの設定オプションを追加します。 必ずドメインとメール情報を自分のドメイン名と連絡先メールアドレスに置き換えてください:

〜/ node_project / docker-compose.yml

...
 certbot:
   image: certbot/certbot
   container_name: certbot
   volumes:
     - certbot-etc:/etc/letsencrypt
     - certbot-var:/var/lib/letsencrypt
     - web-root:/var/www/html
   depends_on:
     - webserver
   command: certonly --webroot --webroot-path=/var/www/html --email  --agree-tos --no-eff-email --staging -d   -d www.

この定義は、Docose Hubからhttps://hub.docker.com/r/certbot/certbot/[certbot/certbot image]をプルするようComposeに指示します。 また、名前付きボリュームを使用して、ドメイン証明書と「+ certbot-etc 」のキー、「 certbot-var 」の作業ディレクトリの暗号化、および「 web-root +」のアプリケーションコードなどのリソースをNginxコンテナと共有します`。

繰り返しますが、「+ depends_on 」を使用して、「 webserver 」サービスの実行後に「 certbot +」コンテナを開始するように指定しました。

コンテナの起動時に実行するコマンドを指定する「+ command 」オプションも含まれています。 次のオプションを指定した ` certonly +`サブコマンドが含まれています。

  • +-webroot +:これは、認証のためにwebrootプラグインを使用してwebrootフォルダーにファイルを配置するようCertbotに指示します。

  • +-webroot-path +:これはwebrootディレクトリのパスを指定します。

  • +-email +:登録と回復に使用するメール。

  • +-agree-tos +:これは、https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf [ACME’s Subscriber Agreement]に同意することを指定します。

  • +-no-eff-email +:これは、Certbotに、https://www.eff.org/ [Electronic Frontier Foundation](EFF)とメールを共有したくないことを伝えます。 必要に応じて、これを省略しても構いません。

  • +-staging +:これにより、CertbotにLet’s Encryptのステージング環境を使用してテスト証明書を取得することを伝えます。 このオプションを使用すると、構成オプションをテストして、ドメイン要求の制限を回避できます。 これらの制限の詳細については、Let’s Encryptのhttps://letsencrypt.org/docs/rate-limits/[rate limits documentation]をご覧ください。

  • + -d +:これにより、リクエストに適用したいドメイン名を指定できます。 この場合、「+」と「 www。+」を含めました。 これらを独自のドメイン設定に置き換えてください。

最後のステップとして、ボリュームとネットワークの定義を追加します。 ここのユーザー名は、必ず自分の非ルートユーザーに置き換えてください。

〜/ node_project / docker-compose.yml

...
volumes:
 certbot-etc:
 certbot-var:
 web-root:
   driver: local
   driver_opts:
     type: none
     device: /home///views/
     o: bind

networks:
 app-network:
   driver: bridge

名前付きボリュームには、Certbot証明書と作業ディレクトリボリューム、およびサイトの静的アセットのボリューム「+ web-root 」が含まれます。 ほとんどの場合、Dockerボリュームのデフォルトドライバーは ` local `ドライバーで、Linuxではhttp://man7.org/linux/man-pages/man8/mount.8.html[` mount + `コマンド]。 これにより、アプリケーションの静的アセットを含むホスト上の `+ views `ディレクトリを実行時にボリュームにマウントする ` driver_opts `を使用して、ドライバーオプションのリストを指定できます。 その後、ディレクトリの内容をコンテナ間で共有できます。 ` views +`ディレクトリの内容の詳細については、https://www.digitalocean.com/community/tutorials/how-to-build-a-node-js-application-with-docker#step-をご覧ください。 2-%E2%80%94-creating-the-application-files [DockerでNode.jsアプリケーションを構築する方法のステップ2]。

終了すると、 `+ docker-compose.yml +`ファイルは次のようになります。

〜/ node_project / docker-compose.yml

version: '3'

services:
 nodejs:
   build:
     context: .
     dockerfile: Dockerfile
   image: nodejs
   container_name: nodejs
   restart: unless-stopped
   networks:
     - app-network

 webserver:
   image: nginx:
   container_name: webserver
   restart: unless-stopped
   ports:
     - "80:80"
   volumes:
     - web-root:/var/www/html
     - ./nginx-conf:/etc/nginx/conf.d
     - certbot-etc:/etc/letsencrypt
     - certbot-var:/var/lib/letsencrypt
   depends_on:
     - nodejs
   networks:
     - app-network

 certbot:
   image: certbot/certbot
   container_name: certbot
   volumes:
     - certbot-etc:/etc/letsencrypt
     - certbot-var:/var/lib/letsencrypt
     - web-root:/var/www/html
   depends_on:
     - webserver
   command: certonly --webroot --webroot-path=/var/www/html --email  --agree-tos --no-eff-email --staging -d   -d www.

volumes:
 certbot-etc:
 certbot-var:
 web-root:
   driver: local
   driver_opts:
     type: none
     device: /home///views/
     o: bind

networks:
 app-network:
   driver: bridge

サービス定義を配置すると、コンテナを起動して証明書リクエストをテストする準備が整います。

手順4-SSL証明書と資格情報の取得

https://docs.docker.com/compose/reference/up/[`docker-compose up + `]でコンテナを起動できます。これにより、指定した順序でコンテナとサービスが作成および実行されます。 ドメインリクエストが成功すると、出力に正しい終了ステータスが表示され、正しい証明書が ` webserver `コンテナーの ` / etc / letsencrypt / live +`フォルダーにマウントされます。

`+ docker-compose up `および ` -d `フラグを使用してサービスを作成します。これにより、バックグラウンドで ` nodejs `および ` webserver +`コンテナが実行されます。

docker-compose up -d

サービスが作成されたことを確認する出力が表示されます。

OutputCreating nodejs ...
Creating webserver ...
Creating certbot   ...

`+docker-compose ps + `を使用して、サービスのステータスを確認します。

docker-compose ps

すべてが成功した場合、「+ nodejs 」および「 web server」サービスは「+ Up」になり、「+ certbot」コンテナは「0」ステータスメッセージで終了します。

Output  Name                 Command               State          Ports
------------------------------------------------------------------------
certbot     certbot certonly --webroot ...   Exit 0
nodejs      node app.js                      Up       8080/tcp
webserver   nginx -g daemon off;             Up       0.0.0.0:80->80/tcp

+ nodejs +`および `+ webserver +`サービスの `+ State +`カラムに `+ Up +`以外のもの、または `+ certbot +`コンテナの `+ 0 +`以外の終了ステータスが表示される場合、 +docker-compose logs + `コマンドでサービスログを確認してください:

docker-compose logs

+docker-compose exec + `を使用して、資格情報が + webserver + `コンテナにマウントされたことを確認できます。

docker-compose exec webserver ls -la /etc/letsencrypt/live

リクエストが成功した場合、次のような出力が表示されます。

Outputtotal 16
drwx------ 3 root root 4096 Dec 23 16:48 .
drwxr-xr-x 9 root root 4096 Dec 23 16:48 ..
-rw-r--r-- 1 root root  740 Dec 23 16:48 README
drwxr-xr-x 2 root root 4096 Dec 23 16:48

リクエストが成功することがわかったので、 `+ certbot `サービス定義を編集して `-staging +`フラグを削除できます。

`+ docker-compose.yml`を開きます:

nano docker-compose.yml

`+ certbot `サービス定義を持つファイルのセクションを見つけ、 ` command `オプションの `-staging `フラグを `-force-renewal `フラグに置き換えます。既存の証明書と同じドメインを持つ新しい証明書を要求したい。 ` certbot +`サービスの定義は次のようになります。

〜/ node_project / docker-compose.yml

...
 certbot:
   image: certbot/certbot
   container_name: certbot
   volumes:
     - certbot-etc:/etc/letsencrypt
     - certbot-var:/var/lib/letsencrypt
     - web-root:/var/www/html
   depends_on:
     - webserver
   command: certonly --webroot --webroot-path=/var/www/html --email  --agree-tos --no-eff-email  -d  -d www.
...

これで、「+ docker-compose up 」を実行して、「 certbot 」コンテナとその関連ボリュームを再作成できます。 また、 `-no-deps `オプションを追加して、Composeに ` webserver +`サービスが既に実行されているため、開始をスキップできることを伝えます。

docker-compose up --force-recreate --no-deps certbot

証明書要求が成功したことを示す出力が表示されます。

Outputcertbot      | IMPORTANT NOTES:
certbot      |  - Congratulations! Your certificate and chain have been saved at:
certbot      |    /etc/letsencrypt/live//fullchain.pem
certbot      |    Your key file has been saved at:
certbot      |    /etc/letsencrypt/live//privkey.pem
certbot      |    Your cert will expire on 2019-03-26. To obtain a new or tweaked
certbot      |    version of this certificate in the future, simply run certbot
certbot      |    again. To non-interactively renew *all* of your certificates, run
certbot      |    "certbot renew"
certbot      |  - Your account credentials have been saved in your Certbot
certbot      |    configuration directory at /etc/letsencrypt. You should make a
certbot      |    secure backup of this folder now. This configuration directory will
certbot      |    also contain certificates and private keys obtained by Certbot so
certbot      |    making regular backups of this folder is ideal.
certbot      |  - If you like Certbot, please consider supporting our work by:
certbot      |
certbot      |    Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
certbot      |    Donating to EFF:                    https://eff.org/donate-le
certbot      |
certbot exited with code 0

証明書を配置したら、Nginx構成の変更に進んでSSLを含めることができます。

ステップ5-Webサーバーの構成とサービス定義の変更

Nginx構成でSSLを有効にするには、HTTPリダイレクトをHTTPSに追加し、SSL証明書とキーの場所を指定する必要があります。 また、https://en.wikipedia.org/wiki/Forward_secrecy [Perfect Forward Secrecy]で使用するDiffie-Hellmanグループの指定も含まれます。

これらの追加を含めるために `+ webserver +`サービスを再作成するので、今すぐ停止できます:

docker-compose stop webserver

次に、現在のプロジェクトディレクトリにDiffie-Hellmanキー用のディレクトリを作成します。

mkdir dhparam

https://www.openssl.org/docs/manmaster/man1/openssl-dhparam.html [+ openssl + command]を使用してキーを生成します。

sudo openssl dhparam -out /home///dhparam/dhparam-2048.pem 2048

キーを生成するのに少し時間がかかります。

関連するDiffie-HellmanおよびSSL情報をNginx構成に追加するには、最初に以前に作成したNginx構成ファイルを削除します。

rm nginx-conf/nginx.conf

ファイルの別のバージョンを開きます。

nano nginx-conf/nginx.conf

次のコードをファイルに追加して、HTTPをHTTPSにリダイレクトし、SSL資格情報、プロトコル、およびセキュリティヘッダーを追加します。 `++`を独自のドメインに置き換えることを忘れないでください:

〜/ node_project / nginx-conf / nginx.conf

server {
       listen 80;
       listen [::]:80;
       server_name  www.;

       location ~ /.well-known/acme-challenge {
         allow all;
         root /var/www/html;
       }

       location / {
               rewrite ^ https://$host$request_uri? permanent;
       }
}

server {
       listen 443 ssl http2;
       listen [::]:443 ssl http2;
       server_name  www.;

       server_tokens off;

       ssl_certificate /etc/letsencrypt/live//fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live//privkey.pem;

       ssl_buffer_size 8k;

       ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

       ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
       ssl_prefer_server_ciphers on;

       ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

       ssl_ecdh_curve secp384r1;
       ssl_session_tickets off;

       ssl_stapling on;
       ssl_stapling_verify on;
       resolver 8.8.8.8;

       location / {
               try_files $uri @nodejs;
       }

       location @nodejs {
               proxy_pass http://nodejs:8080;
               add_header X-Frame-Options "SAMEORIGIN" always;
               add_header X-XSS-Protection "1; mode=block" always;
               add_header X-Content-Type-Options "nosniff" always;
               add_header Referrer-Policy "no-referrer-when-downgrade" always;
               add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
               # add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
               # enable strict transport security only if you understand the implications
       }

       root /var/www/html;
       index index.html index.htm index.nginx-debian.html;
}

HTTPサーバーブロックは、 `+ .well-known / acme-challenge +`ディレクトリへのCertbot更新リクエストのwebrootを指定します。 また、HTTP要求をルートディレクトリにHTTPSに転送するhttp://nginx.org/en/docs/http/ngx_http_rewrite_module.html#rewrite[rewrite directive]も含まれています。

HTTPSサーバーブロックは、「+ ssl 」と「 http2 +」を有効にします。 HTTP / 2がHTTPプロトコルを反復処理する方法とWebサイトのパフォーマンスに与える利点について詳しくは、https://www.digitalocean.com/community/tutorials/how-to-set-up-nginxの概要をご覧ください。 -with-http-2-support-on-ubuntu-18-04 [Ubuntu 18.04でHTTP / 2サポートを使用してNginxをセットアップする方法]。 このブロックには、最新のSSLプロトコルと暗号を使用し、OSCPステープルがオンになっていることを確認するための一連のオプションも含まれています。 OSCPホチキス留めにより、https://www.digitalocean.com/community/tutorials/an-introduction-to-let-s-encrypt#what-is-a-certificate-authority [certificate]からタイムスタンプ付きの応答を提供できます。権限]最初のhttps://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_handshake[TLSハンドシェイク]で認証プロセスを高速化できます。

このブロックは、SSLおよびDiffie-Hellmanの資格情報とキーの場所も指定します。

最後に、http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files [+ try_files +]ディレクティブを持つリクエストブロックを含むプロキシブロック情報をこのブロックに移動し、リクエストをエイリアス化されたNode.jsアプリケーションコンテナー、およびそのエイリアスの場所ブロック。これには、https://www.ssllabs.com/ssltest/ [SSL Labs]などの* A *評価を取得できるようにするセキュリティヘッダーが含まれます。およびhttps://securityheaders.com/[Security Headers]サーバーテストサイト。 これらのヘッダーには、https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options [+ X-Frame-Options +]、https://developer.mozilla.orgが含まれます。 /en-US/docs/Web/HTTP/Headers/X-Content-Type-Options[X-Content-Type-Options]、https://scotthelme.co.uk/a-new-security-header -referrer-policy / [+ Referrer Policy +]、https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy [+ Content-Security-Policy +] 、およびhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection [+ X-XSS-Protection +]。 HTTP + Strict Transport Security +(HSTS)ヘッダーはコメント化されています-意味を理解し、https://hstspreload.orgを評価した場合にのみ、これを有効にします/ [「プリロード」機能]。

編集が完了したら、ファイルを保存して閉じます。

`+ webserver `サービスを再作成する前に、HTTPSの関連ポート情報やDiffie-Hellmanボリューム定義など、 ` docker-compose.yml +`ファイルのサービス定義にいくつかの項目を追加する必要があります。

ファイルを開きます。

nano docker-compose.yml

`+ webserver `サービス定義で、次のポートマッピングと名前付きボリューム ` dhparam +`を追加します。

〜/ node_project / docker-compose.yml

...
webserver:
   image: nginx:latest
   container_name: webserver
   restart: unless-stopped
   ports:
     - "80:80"
     -
   volumes:
     - web-root:/var/www/html
     - ./nginx-conf:/etc/nginx/conf.d
     - certbot-etc:/etc/letsencrypt
     - certbot-var:/var/lib/letsencrypt
     -
   depends_on:
     - nodejs
   networks:
     - app-network

次に、 `+ dhparam `ボリュームを ` volumes +`定義に追加します。

〜/ node_project / docker-compose.yml

...
volumes:
 ...
 dhparam:
   driver: local
   driver_opts:
     type: none
     device: /home///dhparam/
     o: bind

`+ web-root `ボリュームと同様に、 ` dhparam `ボリュームはホストに保存されているDiffie-Hellmanキーを ` webserver +`コンテナにマウントします。

編集が終了したら、ファイルを保存して閉じます。

`+ webserver +`サービスを再作成します:

docker-compose up -d --force-recreate --no-deps webserver

`+ docker-compose ps +`でサービスを確認してください:

docker-compose ps

`+ nodejs `および ` webserver +`サービスが実行されていることを示す出力が表示されるはずです。

Output  Name                 Command               State                     Ports
----------------------------------------------------------------------------------------------
certbot     certbot certonly --webroot ...   Exit 0
nodejs      node app.js                      Up       8080/tcp
webserver   nginx -g daemon off;             Up       0.0.0.0:443->443/tcp, 0.0.0.0:80->80/tcp

最後に、ドメインにアクセスして、すべてが期待どおりに機能していることを確認できます。 ブラウザを「+ https:// 」に移動し、「+」を自分のドメイン名に置き換えてください。 次のランディングページが表示されます。

image:https://assets.digitalocean.com/articles/docker_node_image/landing_page.png [アプリケーションのランディングページ]

ブラウザのセキュリティインジケータにロックアイコンも表示されます。 必要に応じて、https://www.ssllabs.com/ssltest/ [SSL Labsサーバーテストのランディングページ]またはhttps://securityheaders.com/ [セキュリティヘッダーサーバーのテストランディングページ]に移動できます。 含まれる構成オプションにより、サイトの両方で* A *評価が得られます。

ステップ6-証明書の更新

Let’s Encrypt証明書は90日間有効です。そのため、自動更新プロセスを設定して、失効しないようにしてください。 これを行う1つの方法は、 `+ cron `スケジューリングユーティリティでジョブを作成することです。 この場合、証明書を更新してNginxの設定をリロードするスクリプトを使用して、「 cron +」ジョブをスケジュールします。

プロジェクトディレクトリで「+ ssl_renew.sh +」というスクリプトを開きます。

nano ssl_renew.sh

次のコードをスクリプトに追加して、証明書を更新し、Webサーバー構成を再読み込みします。

〜/ node_project / ssl_renew.sh

#!/bin/bash

/usr/local/bin/docker-compose -f /home///docker-compose.yml run certbot renew --dry-run \
&& /usr/local/bin/docker-compose -f /home///docker-compose.yml kill -s SIGHUP webserver

`+ docker-compose `バイナリの場所を指定することに加えて、 ` docker-compose `コマンドを実行するために ` docker-compose.yml `ファイルの場所も指定します。 この場合、 ` docker-compose run `を使用して ` certbot `コンテナを起動し、サービス定義で提供されている ` command `を別のものでオーバーライドします: ` renew `サブコマンドは、期限切れに近づいています。 スクリプトをテストするために、ここに「-dry-run +」オプションを含めました。

次に、スクリプトはhttps://docs.docker.com/compose/reference/kill/[+docker-compose kill + `]を使用してhttps://en.wikipedia.org/wiki/SIGHUP [ + SIGHUP + `を送信しますNginxの設定をリロードするために、 `+ webserver +`コンテナにシグナル]。 このプロセスを使用してNginx設定をリロードする方法の詳細については、https://blog.docker.com/2015/04/tips-for-deploying-nginx-official-image-with-docker/ [このDockerブログ投稿]を参照してください。 Dockerで公式のNginxイメージを展開する]。

編集が終了したら、ファイルを閉じます。 実行可能にします。

chmod +x ssl_renew.sh

次に、* root * `+ crontab +`ファイルを開いて、指定された間隔で更新スクリプトを実行します。

sudo crontab -e

このファイルを初めて編集する場合は、エディターを選択するよう求められます。

crontab

no crontab for root - using an empty one
Select an editor.  To change later, run 'select-editor'.
 1. /bin/ed
 2. /bin/nano        <---- easiest
 3. /usr/bin/vim.basic
 4. /usr/bin/vim.tiny
Choose 1-4 [2]:
...

ファイルの最後に、次の行を追加します。

crontab

...
*/5 * * * * /home///ssl_renew.sh >> /var/log/cron.log 2>&1

これにより、ジョブ間隔が5分ごとに設定されるため、更新リクエストが意図したとおりに機能したかどうかをテストできます。 また、ジョブからの関連する出力を記録するために、ログファイル `+ cron.log +`を作成しました。

5分後、 `+ cron.log +`をチェックして、更新リクエストが成功したかどうかを確認します。

tail -f /var/log/cron.log

更新が成功したことを確認する出力が表示されます。

Output- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates below have not been saved.)

Congratulations, all renewals succeeded. The following certs have been renewed:
 /etc/letsencrypt/live//fullchain.pem (success)
** DRY RUN: simulating 'certbot renew' close to cert expiry
**          (The test certificates above have not been saved.)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Killing webserver ...

これで、 `+ crontab +`ファイルを変更して、毎日の間隔を設定できます。 たとえば、毎日正午にスクリプトを実行するには、ファイルの最終行を次のように変更します。

crontab

...
0 12 * * * /home///ssl_renew.sh >> /var/log/cron.log 2>&1

また、 `+ ssl_renew.sh `スクリプトから `-dry-run +`オプションを削除することもできます。

〜/ node_project / ssl_renew.sh

#!/bin/bash

/usr/local/bin/docker-compose -f /home///docker-compose.yml run certbot renew \
&& /usr/local/bin/docker-compose -f /home///docker-compose.yml kill -s SIGHUP webserver

`+ cron +`ジョブは、Let’s Encrypt証明書が適格になったときに更新することにより、証明書が失効しないようにします。 また、https://www.digitalocean.com/community/tutorials/how-to-manage-logfiles-with-logrotate-on-ubuntu-16-04 [Logrotateユーティリティを使用してログのローテーションを設定]して、ローテーションおよび圧縮することもできます。ログファイル。

結論

コンテナを使用して、NginxリバースプロキシでNodeアプリケーションをセットアップおよび実行しました。 また、アプリケーションのドメインのSSL証明書を保護し、必要に応じてこれらの証明書を更新するための `+ cron +`ジョブを設定しました。

Let’s Encryptプラグインの詳細については、https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-onの使用に関する記事をご覧ください。 -ubuntu-18-04 [Nginxプラグイン]またはhttps://www.digitalocean.com/community/tutorials/how-to-use-certbot-standalone-mode-to-retrieve-let-s-encrypt-ssl- certificate-on-ubuntu-1804 [スタンドアロンプ​​ラグイン]。

次のリソースを参照して、Docker Composeの詳細を確認することもできます。

https://docs.docker.com/compose/ [ドキュメントの作成]は、マルチコンテナアプリケーションについてさらに学ぶための優れたリソースでもあります。