无法将SSL证书添加到NGINX Docker容器

时间:2018-07-18 10:38:15

标签: docker ssl nginx docker-compose ssl-certificate

我正在尝试将SSL证书(使用LetsEncrypt生成)添加到我的nginx中。 nginx是从docker-compose文件构建的,在该文件中,我创建了从主机到容器的卷,以便容器可以访问证书和私钥。

volumes:
  - /etc/nginx/certs/:/etc/nginx/certs/

nginx容器启动并失败并出现以下错误

[emerg] 1#1: BIO_new_file("/etc/nginx/certs/fullchain.pem") failed 
(SSL: error:02001002:system library:fopen:No such file or 
directory:fopen('/etc/nginx/certs/fullchain.pem','r') 
error:2006D080:BIO routines:BIO_new_file:no such file)

我的nginx配置文件如下:

server {
    listen 80;
    server_name server_blah www.server_blah;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name server_blah;
    ssl_certificate      /etc/nginx/certs/fullchain.pem;
    ssl_certificate_key  /etc/nginx/certs/privkey.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;
}

我缺少什么/做错了什么?

3 个答案:

答案 0 :(得分:4)

最后破解了此错误,并能够在我的开发和生产站点上成功重复此过程,以使SSL证书正常工作!

很抱歉,文章的长度!

在我的设置中,我在ubuntu 16机器上安装了docker docker-compose安装程序。

遇到此问题的任何人,我都会详细说明我的操作步骤。

  1. 转到代码所在的目录

    cd /opt/example_dir/

  2. 为letencrypt及其目录创建一个目录。

    sudo mkdir -p /opt/example_dir/letsencrypt/letsencrypt-site

  3. 从letsencrypt目录创建准系统docker-compose.yml文件。

    sudo nano /opt/example_dir/letsencrypt/docker-compose.yml

添加以下内容:

    version: '2'

        services:
            image: nginx:latest
            ports:
              - "80:80"
            volumes:
              - ./nginx.conf:/etc/nginx/conf.d/default.conf
              - ./letsencrypt-site:/usr/share/nginx/html
            networks:
              - docker-network

        networks:
          docker-network:
            driver: bridge

* This will pull down the latest nginx version
* Expose port 80 
* Mount a config file (that i'll create later) 
* Maps the site directory so that we can have a simple test index.html for when 

我们启动简单的nginx容器。

  1. /opt/example_dir/letsencrypt

    中创建nginx.conf文件

    sudo nano /opt/example_dir/letsencrypt/nginx.conf

将以下内容放入其中

    server {
      listen 80;
      listen [::]:80;
      server_name example_server.com;

      location ~ /.well-known/acme-challenge {
          allow all;
          root /usr/share/nginx/html;
      }

      root /usr/share/nginx/html;
      index index.html;
    }

* This listens for requests on port 80 for the server with name example_server.com
* Gives the Certbot agent access to ./well-known/acme-challenge
* Sets the default root and file
  1. 接下来在/opt/example_dir/letsencrypt/letsencrypt-site内创建一个index.html文件

sudo nano /opt/example_dir/letsencrypt/letsencrypt-site/index.html

在其中添加以下内容

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>LetsEncrypt Setup</title>
</head>
<body>

    <p>Test file for our http nginx server</p>
</body>
</html>

####基本的nginx容器的所有零件就位!

  1. 现在我们启动nginx容器。

    cd /opt/example_dir/letsencrypt
    sudo docker-compose up -d
    

nginx容器现已启动并运行,请访问您定义的url,然后应返回测试index.html页面。至此,我们准备运行certbot命令来生成一些证书

  1. 运行以下命令,以用您的电子邮件替换--email的证书

    sudo docker run -it --rm \
    -v /docker-volumes/etc/letsencrypt:/etc/letsencrypt \
    -v /docker-volumes/var/lib/letsencrypt:/var/lib/letsencrypt \
    -v /opt/example_dir/letsencrypt/letsencrypt-site:/data/letsencrypt \
    -v "/docker-volumes/var/log/letsencrypt:/var/log/letsencrypt" \
    certbot/certbot \
    certonly --webroot \
    --email youremail@domain.com --agree-tos --no-eff-email \
    --webroot-path=/data/letsencrypt \
    -d example.com
    
    • 以交互模式运行docker,这样您就可以看到输出。
    • 完成证书生成后,它将自行删除。
    • 它将装入4个卷:
      1. 存储证书的letencrypt文件夹/
      2. 一个lib文件夹
      3. 映射我们的站点文件夹
      4. 映射日志记录路径
    • 它同意ToS
    • 指定根Web路径
    • 指定要为其生成证书的服务器地址。

如果该命令运行正常,那么我们已经为该Web服务器生成了证书。现在,我们可以在生产站点中使用它们,并将nginx配置为使用ssl并利用这些证书!

  1. 关闭Nginx容器

    cd /opt/example_dir/letsencrypt/
    sudo docker-compose down
    

Setup Production Nginx容器

目录结构现在应该看起来像这样。您的代码/网络应用项目所在的位置,然后是我们在上面创建的letencrypt文件夹的位置。

/opt/example_dir
             / -> project_folder
             / -> letsencrypt
  1. 创建文件夹调用dh-param

    sudo mkdir -p /opt/example_dir/project_folder/dh-param
    
  2. 生成dh键

    sudo openssl dhparam -out /opt/example_dir/project_folder/dh-param/dhparam-2048.pem 2048
    
  3. 更新/opt/example_dir/project_folder

  4. 中的docker-compose.yml和nginx.conf文件

project_folder是我的源代码所在的位置,因此我在这里为nginx创建了一个生产配置文件,并更新了docker-compose.yml以安装我的nginx配置,dh-pharam交换密钥以及我们之前创建的证书本身。

docker-compose中的

nginx服务

    nginx:
        image: nginx:1.11.3
        restart: always
        ports:
          - "80:80"
          - "443:443"
          - "8000:8000"
        volumes:
          - ./nginx.conf:/etc/nginx/conf.d/default.conf
          - ./dh-param/dhparam-2048.pem:/etc/ssl/certs/dhparam-2048.pem
          - /docker-volumes/etc/letsencrypt/live/exampleserver.com/fullchain.pem:/etc/letsencrypt/live/exampleserver.com/fullchain.pem
          - /docker-volumes/etc/letsencrypt/live/exampleserver.com/privkey.pem:/etc/letsencrypt/live/exampleserver.com/privkey.pem
        networks:
          - docker-network

        volumes_from:
          - flask
        depends_on:
          - flask
          - falcon
        links:
          - datastore

project_folder中的nginx.conf

error_log /var/log/nginx/error.log warn;

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

    server_name exampleserver.com

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

    #for certbot challenges (renewal process)
    location ~ /.well-known/acme-challenge {
        allow all;
        root /data/letsencrypt;
    }
}

#https://exampleserver.com
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name exampleserver.com;

    server_tokens off;

    ssl_certificate /etc/letsencrypt/live/exampleserver.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/exampleserver.com/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;

    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8;


    # Define the specified charset to the “Content-Type” response header field
    charset utf-8;
}

至此,一切就绪! (最后)

  1. 启动docker容器。

    cd /opt/example_dir/project_folder
    sudo docker-compose up -d
    
    # Check the docker log with:
    sudo docker logs -f -t  
    

我知道这是很多步骤,但这是我所做的,对我有用,希望对其他人有帮助。

答案 1 :(得分:0)

我现在有完全相同的问题。相同的错误代码。

我对.pem文件尝试了不同的操作:

  • 将权限(chmod)更改为:
    • 777
    • 755
    • 600
  • 将所有者(小丑)更改为:
    • nginx(用户在nginx.conf中定义)
    • root
  • 将位置更改为:
    • / etc / ssl / certs
    • / etc / nginx / ssl
    • / etc / letsencrypt / live
  • 将docker安装更改为:
    • ro(只读)
    • rw(读写)

可悲的是,这些解决方案都不适合我。

实际上,即使我在连接到集装箱码头时能够列出(ls)文件,nginx也确实找不到文件。

要提供更多详细信息,我正在Synology DS918 + NAS上运行Docker。

我希望这将有助于找到解决方案! 我将进行尝试并尝试各种尝试,如果能够成功进行,我会回来的!

答案 2 :(得分:0)

我的解决方案:

我通过以下方式将/etc/letsencrypt/live/mydomain.com/映射到/etc/nginx/certs/

volumes:
  - /etc/letsencrypt/live/mydomain.com/:/etc/nginx/certs/

在这种情况下,它已经映射了软符号链接。

lrwxrwxrwx 1 root root   38 Sep 15 00:21 chain.pem -> ../../archive/mydomain.com/chain1.pem
lrwxrwxrwx 1 root root   42 Sep 15 00:21 fullchain.pem -> ../../archive/mydomain.com/fullchain1.pem
lrwxrwxrwx 1 root root   40 Sep 15 00:21 privkey.pem -> ../../archive/mydomain.com/privkey1.pem

最后,我将volume部分更改如下:

volumes:
  - /etc/letsencrypt/archive/mydomain.com/:/etc/nginx/certs/