无法让 SSL 在 Docker 容器中工作

Posted

技术标签:

【中文标题】无法让 SSL 在 Docker 容器中工作【英文标题】:Cannot get SSL to work in Docker container 【发布时间】:2016-02-11 19:34:54 【问题描述】:

首先让我说我不是服务器管理员,有很多事情我不知道。因此,我确信我在设置 Docker 容器的地方犯了一个错误,因为 SSL 不起作用。

容器在 Ubuntu 14.04 上运行 Apache 2.4 和 php 5.6,并链接到 mysql 5.6 Docker 容器。

我从 Docker 的基本设置开始 - Official PHP Repo。以下是相关文件:

Dockefile

FROM php:5.6-apache

RUN apt-get update
RUN apt-get install -y net-tools
RUN docker-php-ext-install pdo pdo_mysql
RUN docker-php-ext-install sockets

RUN a2enmod rewrite
RUN a2enmod ssl

ADD 000-default.conf /etc/apache2/sites-enabled/
ADD default-ssl.conf /etc/apache2/sites-anabled/
ADD apache2.conf /etc/apache2/
ADD www-server/ www-server/

EXPOSE 443

000-default.conf

<VirtualHost *:80>

    ServerAdmin webmaster@localhost
    DocumentRoot /www-server/

    ErrorLog $APACHE_LOG_DIR/error.log
    CustomLog $APACHE_LOG_DIR/access.log combined

</VirtualHost>

<Directory /home/www-server/>
    # allow .htaccess overrides to work
    AllowOverride All
    DirectoryIndex login.html index.html index.php
</Directory>

<Directory /home/www-server/client>
    DirectoryIndex home.html
    Options All
    AllowOverride All
    Require all granted
</Directory>

default-ssl.conf

<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
        ServerAdmin webmaster@localhost
        DocumentRoot /home/www-server

        ErrorLog $APACHE_LOG_DIR/error.log
        CustomLog $APACHE_LOG_DIR/access.log combined

        # Enable/Disable SSL for this virtual host.
        SSLEngine on

        SSLCertificateFile /etc/ssl/certs/site.crt
        SSLCertificateKeyFile /etc/ssl/certs/site.key
        SSLCACertificatePath /etc/ssl/certs/digicert/

     </VirtualHost>
</IfModule>

apache2.conf

Mutex file:/var/lock/apache2 default
PidFile /var/run/apache2/apache2.pid
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
User www-data
Group www-data
HostnameLookups Off
ErrorLog /proc/self/fd/2
LogLevel warn

IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf

# ports.conf
Listen 80
<IfModule ssl_module>
        Listen 443
</IfModule>
<IfModule mod_gnutls.c>
        Listen 443
</IfModule>

<Directory />
        Options FollowSymLinks
        AllowOverride None
        Require all denied
</Directory>

<Directory /home/www-server/>
    Options Indexes FollowSymLinks Includes ExecCGI
    AllowOverride All
    Require all granted
</Directory>

DocumentRoot /home/www-server

AccessFileName .htaccess
<FilesMatch "^\.ht">
        Require all denied
</FilesMatch>

LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%Refereri\" \"%User-Agenti\"" vhost_combined
LogFormat "%h %l %u %t \"%r\" %>s %O \"%Refereri\" \"%User-Agenti\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %O" common
LogFormat "%Refereri -> %U" referer
LogFormat "%User-agenti" agent

CustomLog /proc/self/fd/1 combined

<FilesMatch \.php$>
        SetHandler application/x-httpd-php
</FilesMatch>

# Multiple DirectoryIndex directives within the same context will add
# to the list of resources to look for rather than replace
# https://httpd.apache.org/docs/current/mod/mod_dir.html#directoryindex
DirectoryIndex disabled
DirectoryIndex index.php index.html

IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf

注意:我已经删除了这些文件的不相关部分。

要运行 Docker 容器,我使用这个:

sudo docker run -v /home/src/ssl-cert:/etc/ssl/certs --name app-gateway --link mysql56:mysql -p 80:80 -p 443:443 -d  app-image

这是日志文件的一部分:

::1 - - [10/Nov/2015:19:26:19 +0000] "OPTIONS * HTTP/1.0" 200 152 "-" "Apache/2.4.10 (Debian) PHP/5.6.15 OpenSSL/1.0.1k (internal dummy connection)"
::1 - - [10/Nov/2015:19:26:20 +0000] "OPTIONS * HTTP/1.0" 200 152 "-" "Apache/2.4.10 (Debian) PHP/5.6.15 OpenSSL/1.0.1k (internal dummy connection)"
72.5.190.136 - - [10/Nov/2015:19:26:21 +0000] "\x16\x03\x01" 400 0 "-" "-"
72.5.190.136 - - [10/Nov/2015:19:26:21 +0000] "\x16\x03\x01" 400 0 "-" "-"
72.5.190.136 - - [10/Nov/2015:19:26:21 +0000] "\x16\x03\x01" 400 0 "-" "-"

浏览器出现此错误:

ERR_SSL_PROTOCOL_ERROR

TL;DR 我已经按照我在网上找到的所有步骤在 Docker 容器中安装和使用我的 SSL 证书,但我没有成功让它工作。让 SSL 在 Docker 容器中工作时我忽略了什么明显的东西?

【问题讨论】:

【参考方案1】:

有时,尤其是当您长时间尝试解决问题并且在命令行的控制台窗口中进行编码时,您会错过最简单的事情。看看 Dockerfile 中的这两行:

ADD 000-default.conf /etc/apache2/sites-enabled/
ADD default-ssl.conf /etc/apache2/sites-anabled/

ae 几乎无法区分,因此很难找到拼写错误。 Dockerfile 会正确构建映像并在容器中添加新目录,然后将配置文件放在该目录中。

drwxr-xr-x  2 www www  4096 Nov 11 15:56 sites-anabled
drwxr-xr-x  2 www www  4096 Oct 23 20:19 sites-available
drwxr-xr-x  2 www www  4096 Nov 11 15:56 sites-enabled

由于没有为未知目录引发错误并且映像构建成功,它将运行,但在这种情况下 SSL 将无法正常工作。

【讨论】:

现在受伤了 天哪,确实如此。 几个人错过了@RiggsFolly 这就是为什么我喜欢带有拼写检查器的 IDE :) 谢谢@JayBlanchard,你能分享一下你是如何将ssl密钥插入服务器的吗? @AlexanderMills 这只是个人喜好。我有时会包含来自 URL 的内容,而 COPY 无法做到这一点,所以我这样做是为了保持一致性。在这种情况下,我可以很容易地使用COPY【参考方案2】:

我不想像其他答案那样“添加”文件。 并且 HTML 文件将通过挂载到 /var/www 安装。 我所需要的只是接受 HTTPS (SSL) 的 apache 服务器, 将 HTTP(非 SSL)重定向到 HTTPS,以及一些小的 PHP 配置。

这是我在 DockerFile 中所做的...

# Install PHP Apache as the base image
FROM "php:7.3-apache"

# Install ssl-cert (snakeoil) package
RUN set -eux; \
    apt-get update && apt-get install -y ssl-cert; \
    : "Clean Apt system" ;\
    apt-get clean; \
    rm -rf /var/lib/apt/lists/*; \
    rm -rf /tmp/* /var/tmp/* /var/log/lastlog /var/log/faillog; \
    rm -f /var/log/apt/*,alternatives.log,dpkg.log; \
    :;

# Set up apache with HTTPS redirect
RUN set -eux; \
    : "Time Zone"; \
    ln -sf /usr/share/zoneinfo/Australia/Sydney /etc/localtime; \
    : "Apache Changes" ;\
    # enable SSL \
    a2enmod rewrite ssl; \
    a2ensite default-ssl; \
    cd /etc/apache2/sites-enabled/; \
    sed -i '/<\/VirtualHost>/d'                          000-default.conf; \
    echo 'RewriteEngine On'                           >> 000-default.conf; \
    echo 'RewriteRule . https://%SERVER_NAME [R,L]' >> 000-default.conf; \
    echo '</VirtualHost>'                             >> 000-default.conf; \
    :;

# PHP Configuration
RUN set -eux; \
    cd $PHP_INI_DIR; \
    cp php.ini-production php.ini; \
    cd conf.d ;\
    echo "date.timezone=Australia/Sydney"      > date_timezone.ini; \
    echo "session.gc_probability=1"            > session.ini; \
    echo "session.gc_divisor=100"             >> session.ini; \
    echo "session.gc_maxlifetime=1440"        >> session.ini; \
    echo "session.cookie=1440"                >> session.ini; \
    :;

希望对您有所帮助

【讨论】:

以上是关于无法让 SSL 在 Docker 容器中工作的主要内容,如果未能解决你的问题,请参考以下文章

无法让 SSL 在 Node.js 应用程序中工作

当主机使用dnsmasq并且Google的DNS服务器被防火墙时,DNS无法在docker容器中工作?

让 SSL 在 Xampp 中工作 - 访问被禁止错误

如何让 SSL 在 fsockopen 中工作?

CORS 无法在没有 SSL 证书的 IIS 服务器中工作

如何让 MSSQL 服务容器在 Azure DevOps 管道中工作?