如何使用 Docker 在 HTTPS(SSL 连接)上部署 Next.js 应用程序?

Ixx*_*Ixx 7 ssl https nginx docker next.js

我按照 Next.js 文档中的说明使用 Docker 启动服务器: https: //nextjs.org/docs/deployment#docker-image

使用 http 加载站点可以工作,但 https 返回 SSL 协议错误。

我详细做了什么:

  1. 在我的 DigitalOcean Ubuntu 22.4 服务器上配置了 NGINX 和 cerbot(请注意,该指南适用于 Ubuntu 20)https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal

  2. 复制Dockerfile.dockerignore从文档中链接到我的项目的示例项目:https://github.com/vercel/next.js/tree/canary/examples/with-docker

  3. 构建图像并将其上传到服务器。

  4. 在服务器上启动镜像:docker run -p 80:3000 -p 443:3000 my_image

HTTP 工作得很好 ( https://mysite.mydomain)。使用 HTTPS 时,我会遇到错误,例如ERR_SSL_PROTOCOL_ERROR在 Chrome 和SSL_ERROR_RX_RECORD_TOO_LONGFirefox 上。

有任何想法吗?

swi*_*mer 11

以下步骤说明如何设置多容器 Docker Compose 环境,其中 NGINX 用作 Next.js 应用程序前面的反向代理来处理 SSL 连接(并提供 HTTPS URI)。

第 1 步 - Dockerize Next.js 应用程序

幸运的是,这是Next.js 官方文档本身的一部分。关键步骤是将此 Dockerfile复制到您正在处理的 Next.js 存储库。

陷阱:

  • 最好也复制.dockerignore
  • 设置(output: 'standalone'这样next.config.js
  • 我们将在 Next.js 应用程序前面放置一个反向代理,因此端口Dockerfile(默认为 3000)不会对外公开;没有必要公开暴露该端口
  • 确保镜像已构建:docker build -t nextjs:latest -f Dockerfile .
第 2 步 - 设置 Docker Compose 环境

Docker Compose 环境将有两个正在运行的容器:Next.js 应用程序和 NGINX。

NGINX 镜像可以通过添加第二个镜像来创建Dockerfile

# nginx/Dockerfile

FROM nginx:1.23.3-alpine

COPY nginx.conf /etc/nginx/nginx.conf

EXPOSE 80
EXPOSE 443
Run Code Online (Sandbox Code Playgroud)

从项目根目录构建图像docker build -t nginx:latest -f nginx/Dockerfile nginx

然后,我们可以创建一个docker-compose.yml文件:

version: "3.9"
services:
  nextjs:
    image: nextjs:latest
    container_name: nextjs
    ports:
      - "3000:3000"
    restart: always
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /etc/ssl:/etc/nginx/ssl:ro
    restart: always
Run Code Online (Sandbox Code Playgroud)

陷阱:

  • 现在可以添加一个空的nginx.conf,将在下一步中配置
  • 端口 80 (HTTP) 和 443 (HTTPS) 将公开公开,因此需要打开它们
  • SSL 证书和密钥可通过 Docker 卷获取。假定它们存在于主机中的/etc/ssl. 另一种方法是将它们打包到 NGINX 映像中(例如,添加COPY my_ssl_cert.crt /etc/nginx/ssl/my_ssl_cert.crtDockerfile密钥的 , 同上)
第 3 步 - 将 NGINX 配置为反向代理

例子nginx.conf

# nginx/nginx.conf

events {
}

http {
    upstream nextjs {
        server nextjs:3000;
    }
    server {
        # Redirect HTTP requests to HTTPS.
        listen 80;
        server_name localhost;
        root /srv/public;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl;

        server_name localhost;
        root /srv/public;
        server_tokens off;

        ssl_certificate /etc/nginx/ssl/my_ssl_cert.crt;
        ssl_certificate_key /etc/nginx/ssl/my_ssl_key.key;

        location / {
            try_files $uri $uri/ @nextjs;
        }

        location @nextjs {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto https;
            proxy_set_header X-Forwarded-Ssl on;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_pass http://nextjs;
            proxy_cookie_path / "/; HTTPOnly; Secure";
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

陷阱:

  • 我们可以通过默认主机名引用 Next.js 应用程序,nextjs因为默认情况下 Compose 会为您的应用程序设置单个网络文档
第 4 步 - 部署
  1. 构建两个 Docker 镜像
  2. 将 Docker 映像、SSL 文件发送docker-compose.yml到服务器
  3. 在服务器中,运行docker compose up
  4. 如果需要,用于docker logs [container_name]调试任何问题;curl http://localhost:80curl --insecure https://localhost:443可以帮助