【问题标题】:LetsEncrypt in a Docker (docker-compose) app container not workingDocker(docker-compose)应用程序容器中的 LetsEncrypt 不起作用
【发布时间】:2017-05-19 09:52:25
【问题描述】:

我将 docker-compose 用于 Rails 应用程序以拥有应用程序和数据库容器。为了测试某些应用功能,我需要 SSL...所以我将使用 LetsEncrypt 与自签名。

app使用nginx,服务器是ubuntu 14.04 lts,以phusion乘客docker镜像为基础镜像(轻量级debian)

通常使用 LetsEncrypt,我运行通常的 ./certbot-auto certonly --webroot -w /path/to/app/public -d www.example.com

我的服务器运行 nginx(代理将应用程序传递给容器),所以我跳入容器运行 certbot 命令没有问题。

但是,当我尝试转到 https://test-app.example.com 时,它不起作用。我不知道为什么。

现场错误(Chrome):

This site can’t be reached

The connection was reset.

Curl 给出了更好的错误:

curl: (35) Unknown SSL protocol error in connection to test-app.example.com

服务器 nginx app.conf

upstream test_app { server localhost:4200; }
server {
  listen 80;
  listen 443 default ssl;
  server_name test-app.example.com;

  # for SSL
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_dhparam /etc/ssl/dhparam.pem;
  ssl_prefer_server_ciphers on;
  ssl_ciphers 'ECDHE-RSA-blahblahblah-SHA';

  location / {
    proxy_set_header Host $http_host;
    proxy_pass http://test_app;
  }
}

容器的 nginx app.conf

server {
  server_name _;
  root /home/app/test/public;

  ssl_certificate /etc/letsencrypt/live/test-app.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/test-app.example.com/privkey.pem;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_dhparam /etc/ssl/dhparam.pem;
  ssl_prefer_server_ciphers on;
  ssl_ciphers 'ECDHE-RSA-blahblah-SHA';

  passenger_enabled on;
  passenger_user app;
  passenger_ruby /usr/bin/ruby2.3;
  passenger_app_env staging;

  location /app_test/assets/ {
    passenger_enabled off;
    alias /home/app/test/public/assets/;

    gzip_static on;
    expires +7d;
    add_header Cache-Control public;
    break;
  }
}

在我的 Dockerfile 中,我有:

# expose port
EXPOSE 80
EXPOSE 443

在我的 docker-compose.yml 文件中,我有:

test_app_app:
  build: "."
  env_file: config/test_app-application.env
  links:
  - test_app_db:postgres
  environment:
    app_url: https://test-app.example.com
  ports:
  - 4200:80

docker ps 显示为:

Up About an hour    443/tcp, 0.0.0.0:4200->80/tcp 

我现在怀疑这是因为服务器的 nginx——“前置”服务器——没有证书,但我无法在没有应用程序位置的情况下运行 LetsEncrypt 命令。

我尝试在服务器上运行手动 LetsEncrypt 命令,但因为我大概暴露了 80 端口,所以我得到了这个:socket.error: [Errno 98] Address already in use我在这里错过了什么吗?

我该怎么办?

【问题讨论】:

    标签: ruby-on-rails ssl nginx docker-compose lets-encrypt


    【解决方案1】:

    有趣的一个。

    我倾向于同意这可能是由于没有获得证书。

    首先阅读我最后的免责声明。我会尝试使用DNS authentication.,恕我直言,这对于像 Docker 这样的东西来说是一种更好的方法。一些想法浮现在脑海。最容易回答您的问题的是一个 docker 入口点脚本,它首先获取证书然后启动 nginx:

    #!/bin/bash
    set -ea
    
    #get cert
    ./certbot-auto certonly --webroot -w /path/to/app/public -d www.example.com
    
    #start nginx
    nginx
    

    这是“好的”解决方案,恕我直言,但并不是真正的“自动化”(这是让我们加密目标的一部分)。它并没有真正解决在路上更新证书的问题。如果这不是您关心的问题,那么您就去吧。

    您可以真正参与并创建一个入口点脚本来检测证书何时过期,然后重新运行命令以更新它,然后重新加载 nginx。

    一个更复杂(但也更具可扩展性的解决方案)是创建一个 docker 映像,它的唯一目的是处理lets_encrypt 证书和续订,然后提供一种将这些证书分发到其他容器的方法,例如:nfs (或共享 docker 卷,如果您真的小心的话)。

    对于将来阅读此内容的任何人:这是在 compose hooks 成为可用功能之前编写的,这将是迄今为止处理此类事情的最佳方式。

    请阅读此免责声明:

    Docker 并不是最好的解决方案,恕我直言。 Docker 镜像应该是静态数据。因为让加密证书在 3 个月后过期,这意味着您的容器应该有三个月或更短的保质期(或者,就像我上面所说的,考虑更新)。 “没关系!”我听你说。但这也意味着您每次启动容器时都会不断地获得一个新证书(使用入口点方法)。至少,这意味着以前的证书每次都会被吊销。我不知道使用 Lets Encrypt 执行此操作的后果是什么。他们可能只会给你这么多的撤销,然后才会认为发生了可疑的事情。

    我最常做的实际上是使用配置管理并使用 nginx 作为主机系统上的“前端”。或者依靠其他一些机制来处理 SSL 终止。但这并不能回答您关于如何让 Lets Encrypt 与 docker 一起工作的问题。 :-)

    我希望这对您有所帮助或为您指明更好的方向。 :-)

    【讨论】:

    • 谢谢@nick-burke 我会做一个简单的解决方案(因为它真的是一个测试应用程序,甚至不会持续 90 天),虽然在阅读了你的其余帖子之后,听起来像最终购买证书可能是更好的选择。然后主机服务器的 nginx 可以正确地解决问题,并且仍然让 docker 容器无忧无虑地完成它的工作。 (不幸的是,我们需要使用 docker——我个人不会选择它,但这就是 cookie 崩溃的方式)。希望简单的解决方案有效!
    • @rbatta 我真的很喜欢 docker,只需要知道它的优点和缺点。我倾向于将 Lets Encrypt 用于开发环境或按需测试环境。这样一来,您就无需申请资金或通过申请 $$ 来分配真实证书的麻烦。
    • 不幸的是,简单的解决方案不起作用。但在与客户的运营主管交谈后,我错过了所有这些最简单的解决方案......只需复制 SSL 证书让主机服务器了解它。
    【解决方案2】:

    我知道我错过了一件小事。如问题所述,由于服务器上的 nginx 是“面向前端”的 nginx,容器的 nginx 专门用于应用程序,因此服务器的 nginx 需要了解 SSL。

    答案非常简单。把证书复制过来! (感谢我客户的运营负责人)

    我在docker容器中catfullchain.pemprivkey.pem,并在服务器上的/etc/ssl中创建了关联文件。

    在服务器的/etc/nginx/sites-enabled/app.conf我加了:

      ssl_certificate /etc/ssl/test-app-fullchain.pem;
      ssl_certificate_key /etc/ssl/test-app-privkey.pem;
    

    检查配置并重新启动 nginx。繁荣!像魅力一样工作。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-10
      • 1970-01-01
      • 2023-04-11
      • 2020-02-13
      • 2021-10-29
      • 2019-06-07
      • 1970-01-01
      相关资源
      最近更新 更多