docker - 将 SSL 证书添加到 NGINX docker 容器

标签 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;
}

我错过了什么/做错了什么?

最佳答案

终于破解了这个并且能够在我的开发和生产网站上成功地重复这个过程来获得 SSL 证书!

抱歉文章太长了!

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

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

  1. 转到代码所在的目录

    cd /opt/example_dir/

  2. 为 letsencrypt 和它的站点创建一个目录。

    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. 存放证书的letsencrypt文件夹/
      2. 一个库文件夹
      3. 映射我们的站点文件夹
      4. 映射日志记录路径
    • 同意 ToS
    • 指定根网络路径
    • 指定要为其生成证书的服务器地址。

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

  1. 关闭nginx容器

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

设置生产 nginx 容器

目录结构现在应该是这样的。你有你的代码/网络应用程序项目,然后是我们在上面创建的 letsencrypt 文件夹。

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

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

    sudo openssl dhparam -out /opt/example_dir/project_folder/dh-param/dhparam-2048.pem 2048
    
  3. 更新 /opt/example_dir/project_folder 内的 docker-compose.yml 和 nginx.conf 文件

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

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  
    

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

关于docker - 将 SSL 证书添加到 NGINX docker 容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51399883/

相关文章:

python - 有没有一种方法可以安排 docker 容器相互运行?

javascript - 如何构建 React 应用程序的 docker 镜像?

php - SMTP 服务器有问题?

c++ - 从服务器收到 FIN 但连接挂起与 libcurl

angular - 在与根文件夹不同的文件夹中部署Angular应用

docker - 如何模拟 500-50000 个 worker ( docker )节点网络?

docker - 如何在docker compose 3中替换memswap_limit?

java - 验证 SSL 认证 Java/Android

node.js - 在同一端口上使用 Node.js Express 和 TCP 服务器配置 NGINX?

django - 如何配置 nginx 以将 mp4 视频正确提供给 Safari?