【问题标题】:How to expose an nginx docker container via Apache 2 with SSL?如何通过带有 SSL 的 Apache 2 公开 nginx docker 容器?
【发布时间】:2018-12-25 14:59:00
【问题描述】:

我的 Digital Ocean 液滴上的 docker 容器上运行了一个 Web 应用程序。该应用程序有自己的容器,并通过地址 0.0.0.0:8080 上的 Nginx 容器提供服务。 这是 nginx 配置文件:

server {
    listen 80;
    index index.php index.html;
    root /var/www/public;

    location / {
        try_files $uri /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

还有我的 nginx 容器 dockerfile:

FROM nginx:1.10

ADD ./vhost.conf /etc/nginx/conf.d/default.conf
WORKDIR /var/www

现在,我有一个域,我使用 certbot 生成了一个 SSL 证书,我想通过这个域为我的应用程序提供服务,但我失败了。

我正在使用(或尝试)Apache2 作为反向代理,但我无法让它工作。我现在可以访问应用程序的主页,但没有任何资源,因为该页面是通过 https 提供的,但资源是通过 http 从容器中获取的。我不知道我已经尝试了多少东西,但我无处可去。任何帮助将非常感激。 这是我的虚拟主机配置,如果有帮助的话。

vhost-le-ssl.conf:

<IfModule mod_ssl.c>
#Listen 443
#NameVirtualHost *:443
<VirtualHost *:443>

     SSLEngine  On

        # Set the path to SSL certificate
    # Usage: SSLCertificateFile /path/to/cert.pem

 SSLCertificateFile /etc/letsencrypt/live/antonioquadrado.com/cert.pem

    # Servers to proxy the connection, or;
    # List of application servers:
    # Usage:
    # ProxyPass / http://[IP Addr.]:[port]/
    # ProxyPassReverse / http://[IP Addr.]:[port]/
    # Example: 
    ProxyPass / http://0.0.0.0:8080/
    ProxyPassReverse / http://0.0.0.0:8080/

        ServerName antonioquadrado.com
        ServerAlias www.antonioquadrado.com

        ServerAdmin webmaster@localhost
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
RewriteEngine on
# Some rewrite rules in this file were disabled on your HTTPS site,
# because they have the potential to create redirection loops.

# RewriteCond %{SERVER_NAME} =antonioquadrado.com [OR]
# RewriteCond %{SERVER_NAME} =www.antonioquadrado.com
# RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/antonioquadrado.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/antonioquadrado.com/privkey.pem
</VirtualHost>
</IfModule>

vhost.conf:

VirtualHost *:80>

        ProxyPreserveHost On

    # Servers to proxy the connection, or;
    # List of application servers:
    # Usage:
    # ProxyPass / http://[IP Addr.]:[port]/
    # ProxyPassReverse / http://[IP Addr.]:[port]/
    # Example: 
    ProxyPass / https://0.0.0.0:8080/
    ProxyPassReverse / https://0.0.0.0:8080/

        ServerName antonioquadrado.com
        ServerAlias www.antonioquadrado.com

        ServerAdmin webmaster@localhost
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf
RewriteEngine on
RewriteCond %{SERVER_NAME} =antonioquadrado.com [OR]
RewriteCond %{SERVER_NAME} =www.antonioquadrado.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

我已经按照this数字海洋教程了解了这一点。

提前致谢!

编辑:在@SmileIt 指向 serverfault 答案后,我已将我的虚拟主机配置更新为:

<VirtualHost *:80>
        ServerName antonioquadrado.com
        ServerAlias www.antonioquadrado.com

        Redirect permanent / https://www.antonioquadrado.com/
</VirtualHost>

ssl 虚拟主机:

<IfModule mod_ssl.c>
<VirtualHost *:443>

        ServerName www.antonioquadrado.com
        DirectoryIndex index.php index.html
        SetOutputFilter SUBSTITUTE,DEFLATE

        ProxyPass / http://0.0.0.0:8080/
        ProxyPassReverse / http://0.0.0.0:8080/

        AddOutputFilterByType SUBSTITUTE text/html
        Substitute "s|http://0.0.0.0:8080/|https://www.antonioquadrado.com/|i"

        SSLEngine on
        SSLProtocol all -SSLv2
        SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
        Include /etc/letsencrypt/options-ssl-apache.conf
        SSLCertificateKeyFile /etc/letsencrypt/live/antonioquadrado.com/privkey.pem
        SSLCertificateFile /etc/letsencrypt/live/antonioquadrado.com/fullchain.pem
        #SSLCertificateChainFile /path-to/chain.pem
        <Proxy *>
                Order deny,allow
                Allow from all
                Allow from localhost
        </Proxy>
</VirtualHost>
</IfModule>

但是我对通过 http 通过内部 ip 获取的资源有同样的错误。

这也是我的 docker-compose 文件:

version: '2'
services:
    web:
        build:
            context: ./
            dockerfile: web.docker
        volumes:
            - ./:/var/www
        ports:
            - "8080:80"
        links:
            - app
    app:
        build:
            context: ./
            dockerfile: app.docker
        volumes:
            - ./:/var/www
        links:
            - database
        environment:
            - "DB_PORT=3306"
            - "DB_HOST=database"
    database:
        image: mysql:5.6
        environment:
            - "MYSQL_ROOT_PASSWORD=*****"
            - "MYSQL_DATABASE=*******"
        ports:
            - "33061:3306"

【问题讨论】:

  • SF 有解决方案(serverfault.com/questions/884862/…)。我还建议您将“ port_in_redirect off; ”(不带引号)添加到您的 nginx 配置中。此外,您提供的配置正在侦听端口 80 而不是 8080。
  • 在 docker-compose 文件中,端口 80 映射到 8080,所以这不是问题。我在你放在这里的答案中尝试了解决方案,但我没有运气。实际上没有改变,不能真正告诉我做错了什么。我已经使用更新的虚拟主机 confs 和 docker-compose 编辑了我的问题。
  • 我假设您重新启动/重新加载了 apache 并且没有错误正确吗? Mod_substitute 应该重写您的 HTML 以不包含 docker env url。
  • 您的 HTTP 端口 80 配置上没有替代过滤器。您是通过 HTTPS 还是 HTTP 访问网站?
  • 是的,我重启了 apache 几次。有时它什么也没做,但我仍然尝试......有时它似乎是缓存问题,所以我使用htcacheclean -r 尝试清理它但仍然......你的意思是我的 HTTP 端口 80 没有替代过滤器在上面?我也应该在那里添加替代指令吗?

标签: apache docker ssl nginx


【解决方案1】:

Apache 输出过滤器很可能出现故障。

将以下内容添加到顶部附近的 VirtualHost 配置中并重新启动 Apache。

SetOutputFilter SUBSTITUTE;DEFLATE

基本上我们必须告诉 Apache 订购输出过滤器。先替换再放气。如果这对您不起作用,请将以下内容添加到您的 VirturalHost 配置并发送输出。

LogLevel trace3 rewrite:error filter:trace8

输出应该告诉我们在替换过滤器之前运行了哪些过滤器。

【讨论】:

  • 我还必须将此行添加到我的 vhosts 配置 SubstituteMaxLineLength 10m 以使其完全正常工作,因为我在 apache 日志上收到错误说 URI 太长。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
  • 2017-08-11
  • 2021-09-23
  • 2019-01-20
  • 2019-03-22
  • 2017-03-31
  • 1970-01-01
相关资源
最近更新 更多