首页 > web前端 > js教程 > 正文

Docker 容器中 SSL 的挑战无人谈论

Mary-Kate Olsen
发布: 2024-10-06 18:38:03
原创
732 人浏览过

The Challenge About SSL in Docker Containers No One Talks About

如果您曾在 Docker 环境中设置 SSL 方面遇到困难,那么您并不孤单。 SSL 对许多人来说可能是一个令人生畏的障碍,但保护您的应用程序至关重要,尤其是当它暴露在互联网上时。在这篇文章中,我将指导您添加 Nginx 和 Certbot,以便在 Docker 化设置中生成 Let's Encrypt SSL。这使您可以自动续订证书并以最小的麻烦确保您的环境安全。

让我们开始吧!

先决条件

  • Docker 和 Docker Compose 安装在您的计算机上。
  • 对 Docker Compose 和 Nginx 的基本了解。
  • 指向您服务器的域名。

在此示例中,我们使用 Nginx 作为反向代理并使用 Certbot 来管理 SSL 证书。下面,您将找到 docker-compose.yml、用于自动重新加载 Nginx 的 shell 脚本,以及设置所有内容所需的配置文件。

Docker 撰写配置

首先,让我向您展示用于设置 Nginx 和 Certbot 的 Docker Compose 配置。


# docker-compose.yml

services:
  nginx:
    container_name: nginx
    image: nginx:latest
    restart: unless-stopped
    env_file: .env
    networks:
      - your-app-network # Update this with your application service network
    ports:
      - 80:80
      - 443:443
    depends_on:
      - your-app # Your application service
    volumes:
      - ./nginx/secure/:/etc/nginx/templates/
      - /etc/localtime:/etc/localtime:ro
      - ./nginx/certbot/conf:/etc/letsencrypt
      - ./nginx/certbot/www:/var/www/certbot
      - ./nginx/99-autoreload.sh:/docker-entrypoint.d/99-autoreload.sh  # Script to autoreload Nginx when certs are renewed

  certbot:
    image: certbot/certbot
    volumes:
      - ./nginx/certbot/conf:/etc/letsencrypt
      - ./nginx/certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"  # Renew certificates every 12 hours


登录后复制

这个 Docker Compose 文件定义了两个服务:

  • Nginx:充当反向代理并向您的后端提供请求。
  • Certbot:负责使用 Let's Encrypt 生成和更新 SSL 证书。

certbot 服务无限循环运行,每 12 小时更新一次证书。证书存储在共享卷(./nginx/certbot/conf)中,允许Nginx访问最新的证书文件。

Nginx 配置

Nginx 充当反向代理,处理 HTTP 和 HTTPS 流量。对于初始请求,Certbot 需要 HTTP(端口 80)来完成域验证过程。


# default.conf.template

server {
    listen 80;
    server_name ${APP_DOMAIN};

    location / {
        return 301 https://$host$request_uri;
    }

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
}

server {
    listen 443 ssl;
    server_name ${APP_DOMAIN};
    server_tokens off;
    client_max_body_size 20M;

    ssl_certificate /etc/letsencrypt/live/${APP_DOMAIN}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/${APP_DOMAIN}/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Url-Scheme $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://my-app:3000; // Your app service name
    }
}


登录后复制

在上面的配置文件中,Nginx 执行以下操作:

  1. 将 HTTP 请求重定向到 HTTPS 以确保安全通信。
  2. 处理 SSL 终止和对后端服务的代理请求(例如,my-app:3000)。

自动重新加载 Nginx 配置

SSL证书更新后,需要重新加载Nginx以应用更新的证书。要自动化此过程,请添加一个简单的自动重新加载脚本:


# 99-autoreload.sh

#!/bin/sh
while :; do
    # Optional: Instead of sleep, detect config changes and only reload if necessary.
    sleep 6h
    nginx -t && nginx -s reload
done &


登录后复制

此脚本在 Nginx 容器内运行,并每 6 小时或每当证书更新时重新加载 Nginx。

环境变量

创建一个 .env 文件来存储您的域名和电子邮件地址以供 Certbot 注册:


# .env file

APP_DOMAIN=your-domain.com
SSL_EMAIL=contact@your-domain.com


登录后复制

初始 SSL 证书生成

在 Nginx 可以提供 HTTPS 流量之前,您需要生成初始 SSL 证书。使用以下 bash 脚本 (init-letsencrypt.sh) 生成 SSL 证书:


#!/bin/bash

# Source the .env file
if [ -f .env ]; then
  export $(grep -v '^#' .env | xargs)
fi

if ! [ -x "$(command -v docker compose)" ]; then
    echo 'Error: docker compose is not installed.' >&2
    exit 1
fi

domains=(${APP_DOMAIN:-example.com})
rsa_key_size=4096
data_path="./nginx/certbot"
email="${SSL_EMAIL:-hello@example.com}" # Adding a valid address is strongly recommended
staging=0 # Set to 1 if you're testing your setup to avoid hitting request limits

if [ -d "$data_path" ]; then
    read -p "Existing data found for $domains. Continue and replace existing certificate? (y/N) " decision
    if [ "$decision" != "Y" ] && [ "$decision" != "y" ]; then
        exit
    fi
fi

if [ ! -e "$data_path/conf/options-ssl-nginx.conf" ] || [ ! -e "$data_path/conf/ssl-dhparams.pem" ]; then
    echo "### Downloading recommended TLS parameters ..."
    mkdir -p "$data_path/conf"
    curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf >"$data_path/conf/options-ssl-nginx.conf"
    curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem >"$data_path/conf/ssl-dhparams.pem"
    echo
fi

echo "### Creating dummy certificate for $domains ..."
path="/etc/letsencrypt/live/$domains"
mkdir -p "$data_path/conf/live/$domains"
docker compose -f "docker-compose.yml" run --rm --entrypoint "\
  openssl req -x509 -nodes -newkey rsa:$rsa_key_size -days 1\
    -keyout '$path/privkey.pem' \
    -out '$path/fullchain.pem' \
    -subj '/CN=localhost'" certbot
echo

echo "### Starting nginx ..."
docker compose  -f "docker-compose.yml" up --force-recreate -d nginx
echo

echo "### Deleting dummy certificate for $domains ..."
docker compose  -f "docker-compose.yml" run --rm --entrypoint "\
  rm -Rf /etc/letsencrypt/live/$domains && \
  rm -Rf /etc/letsencrypt/archive/$domains && \
  rm -Rf /etc/letsencrypt/renewal/$domains.conf" certbot
echo

echo "### Requesting Let's Encrypt certificate for $domains ..."
#Join $domains to -d args
domain_args=""
for domain in "${domains[@]}"; do
    domain_args="$domain_args -d $domain"
done

# Select appropriate email arg
case "$email" in
"") email_arg="--register-unsafely-without-email" ;;
*) email_arg="--email $email" ;;
esac

# Enable staging mode if needed
if [ $staging != "0" ]; then staging_arg="--staging"; fi

docker compose -f "docker-compose.yml" run --rm --entrypoint "\
  certbot certonly --webroot -w /var/www/certbot \
    $staging_arg \
    $email_arg \
    $domain_args \
    --rsa-key-size $rsa_key_size \
    --agree-tos \
    --force-renewal" certbot
echo

#echo "### Reloading nginx ..."
docker compose -f "docker-compose.yml" exec nginx nginx -s reload



登录后复制

概括

总之,上面提供的配置将 Nginx 设置为 Docker 化应用程序的反向代理,并由 Certbot 自动管理 Let's Encrypt SSL 证书。此设置可确保与您的应用程序的安全连接,而无需手动续订 SSL。

最后的注释

要首次调出您的环境,请使用:


chmod a+x init-letsencrypt.sh
./init-letsencrypt.sh


登录后复制

以下时间您可以使用常用的 docker compose 命令启动您的环境:


docker-compose up -d


登录后复制

确保您的域名指向您的服务器,并且端口 80 和 443 已打开以允许访问 HTTP 和 HTTPS 流量。

如果您遇到任何问题或有改进建议,请在下面的评论中告诉我!我很乐意帮助解决问题或扩展特定主题。

以上是Docker 容器中 SSL 的挑战无人谈论的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!