web-dev-qa-db-ja.com

nginxはdockerコンテナーにリダイレクトします

私の問題を投稿する前に、私が望むことを達成することさえ可能かどうかを知りたいです。

たとえば、myserver.comでnginxとletsencryptを使用してDockerコンテナーを実行しています。同じサーバー上に、Webサイトを実行しているさらに2つのDockerコンテナーがあります。

現時点ではすべてが正常にリダイレクトされるため、www.myserver.comはdocker 1に移動し、site2.myserver.comはdocker 2に移動します。

すべての通信をHTTPSで実行したいのですが、ここで問題が発生します。したがって、私の質問は、nginxとletsencryptを使用するdockerが、letsencryptからの証明書を使用して別のdockerに接続することは可能ですか?私にとって、それはある種の中間者「攻撃」のようです。もう少し回路図:

Http:// site2.myserver.com-> nginxにアクセスしてhttps:// site2.myserver.comにリダイレクトします->ポート80でコンテナ2(192.168.0.10)に接続します。または、別のオプション:http://にアクセスしますsite2.myserver.com-> nginxはhttps:// site2.myserver.comにリダイレクトします-> site2.myserver.com証明書を持つポート443のコンテナー2(192.168.0.10)に接続します。

それができない場合、解決策は何ですか?証明書をDockerコンテナーにコピーしてhttpsを実行させると、httpリクエストがそのコンテナーのhttpsポートにリダイレクトされますか?

Http:// site2.myserver.comにアクセスします-> nginxがリクエストを転送します-> site2.myserver.com証明書を持つポート443でコンテナ2(192.168.0.10)に接続します。

ありがとう、グレギー

6
Greggy

私が理解しているように、あなたのnginxリバースプロキシはコンテナと同じネットワーク上にあるので、TLSでそれらの間の接続を保護する必要はあまりありません(これはプライベートネットワークであり、攻撃者がそのネットワークにアクセスできる場合、彼はサーバーへのアクセス、およびすべての暗号化されていないデータ)。

ローカルネットワーク上の接続を保護するために有効な証明書が絶対に必要な場合は、ローカルIPに解決する追加のサブドメインを作成できます。次に、手動DNSオプションを使用して証明書を取得する必要があります(これは、ドメインのTXTエントリとしてキーを手動で入力する必要があるcertbotオプションです)。

HttpをhttpsにリダイレクトするNginx構成の例

server {
    listen 80;

    server_name example.com;
    return 301 https://example.com/;
}
server{
    listen 443 ssl http2;

    server_name  example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/fullchain.pem;

    location / {
        proxy_pass http://container:8080/;
        proxy_set_header Host $Host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    include tls.conf;
}
7
Paul Trehiou

これが私のやり方です:

NGINX構成ファイル(default.conf)

https://github.com/KyleAMathews/docker-nginx のDockerイメージを使用して、次のようにカスタムのデフォルトファイルを作成しました。

server {
    root /var/www;
    index index.html index.htm;

    server_name localhost MYHOST.COM;

    # Add 1 week expires header for static assets
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires 1w;
    }

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to redirecting to index.html
        try_files $uri $uri/ @root;

        return 301 https://$Host$request_uri;
    }

    # If nginx can't find a file, fallback to the homepage.
    location @root {
        rewrite .* / redirect;
    }

    include /etc/nginx/basic.conf;
}

Dockerfile

これが私のDockerfileです。静的コンテンツがhtml /ディレクトリの下にあることを考慮しています。

COPY conf/default.conf /etc/nginx/sites-enabled/default

ADD certs/myhost.com.crt /etc/nginx/ssl/server.crt
ADD certs/myhost.com.key /etc/nginx/ssl/server.key
RUN ln -s /etc/nginx/sites-available/default-ssl /etc/nginx/sites-enabled/default-ssl

COPY html/ /var/www

CMD 'nginx'

テスト中

ローカルテストの場合は、myhost.comを127.0.0.1に追加してファイル/ etc/hostsを変更し、次のコマンドを実行します。

curl -I http://www.myhost.com/

結果

HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Sun, 04 Mar 2018 04:32:04 GMT
Content-Type: text/html
Content-Length: 178
Connection: keep-alive
Location: https://www.myhost.com/
X-UA-Compatible: IE=Edge

私はすぐに使えるソリューションで行きます:

JWilder Nginx +暗号化しましょう。

まず、NGINX Containerをリバースプロキシとして起動します。

docker run -d -p 80:80 -p 443:443 \
    --name nginx-proxy \
    -v /path/to/certs:/etc/nginx/certs:ro \
    -v /etc/nginx/vhost.d \
    -v /usr/share/nginx/html \
    -v /var/run/docker.sock:/tmp/docker.sock:ro \
    jwilder/nginx-proxy

次に、Lets Encryptコンテナを開始します。

docker run -d \
-v /path/to/certs:/etc/nginx/certs:rw \
--volumes-from nginx-proxy \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
jrcs/letsencrypt-nginx-proxy-companion

あなたのウェブサイトでは、いくつかの環境変数を設定する必要があります:

docker run -d \
--name website1 \
-e "VIRTUAL_Host=website1.com" \
-e "LETSENCRYPT_Host=website1.com" \
-e "[email protected]" \
tutum/Apache-php

Nginxコンテナは彼の設定に新しいエントリを作成し、レット暗号化コンテナは証明書を要求します(そして更新を行います)。

もっと: Nginx + LetsEncrypt

2
opHASnoNAME

いいですね、opHASnoNAMEとPaul Trehiouの答えをマージすることで、最終的に私が望んでいたものを得ることができました。 opHASnoNAMEの答えの追加として私がしたことは、nginxとletsencrypt Dockerの間にファイルシステムをマウントすることです。 nginxの設定ファイルを適切な証明書にリンクすることができます(後述)。

これは私がやったことです:

docker run --name nginx-prod --restart always -d -p 80:80 -p 443:443 -v /choose/your/dir/letsencrypt:/etc/nginx/certs:ro -v /etc/nginx/vhost.d -v /usr/share/nginx/html -v /var/run/docker.sock:/tmp/docker.sock:ro -e DEFAULT_Host=myserver.com jwilder/nginx-proxy

docker run --name letsencrypt --restart always -d -v /choose/your/dir/letsencrypt:/etc/nginx/certs:rw --volumes-from nginx-prod -v /var/run/docker.sock:/var/run/docker.sock:ro jrcs/letsencrypt-nginx-proxy-companion

次に、Webサーバーで任意のコンテナーを実行します。 LETSENCRYPT変数を設定する必要はありません。現在のコンテナは設定しなくてもアクセスできます。

Jwilder/nginx-proxyは、/ etc/nginx/conf.d/default.confで実行中のすべてのコンテナをリストします。次の再起動時に上書きされるため、このファイルには何も追加しないでください。 Webサーバーごとに、同じディレクトリに新しい.confファイルを作成します。このファイルには、Paul Trehiouによって提案されたhttps情報が含まれます。私は例site2.confを作成しました:

server{
    listen 443 ssl http2;
    server_name  site2.myserver.com;
    ssl_certificate /etc/nginx/certs/live/myserver.com/fullchain.pem;
    ssl_certificate_key /etc/nginx/certs/live/myserver.com/privkey.pem;
    ssl_trusted_certificate /etc/nginx/certs/live/myserver.com/fullchain.pem;

    location / {
        proxy_pass http://192.168.0.10/;
        proxy_set_header Host $Host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Proxy_passアドレスは、default.confファイルから取得できるものであり、IPアドレスは各コンテナーにそこにリストされます。これらの.confファイルをバックアップできるように、nginxコンテナーを再作成して、ローカルファイルシステムを/etc/nginx/conf.dにマウントします。 .confファイルのエラーが原因でコンテナが起動しない場合にも、これは容易になります。

あなたのご意見をありがとうございました。パズルが完成しました;-)

0
Greggy