停止配置 Nginx:使用 HTTPS 部署 Go 与 React 的最简方法

发布: (2026年2月11日 GMT+8 09:19)
5 分钟阅读
原文: Dev.to

Source: Dev.to

《停止配置 Nginx》封面图:使用 HTTPS 部署 Go 与 React 的最简方法

“It Works on My Machine” 陷阱

我们都有过这种经历。你花了数周时间构建一个健壮的应用。你的 Go 后端飞快,React 前端流畅,一切在 localhost:8080 上运行得完美无缺。

但随后进入部署阶段。突然之间,你要面对 VPS 配置、SSL 证书、看起来像象形文字的 Nginx 配置文件,以及令人头疼的 CORS 错误。

我最近用 Go 和 PostGIS 构建了 Geo Engine,一个地理空间后端服务。我想把它部署到带有自定义域名和 HTTPS 的 DigitalOcean Droplet 上,但又不想花几个小时去配置 Certbot 或管理复杂的 Nginx 指令。

下面就是我使用 Docker ComposeCaddy(拯救你理智的 Web 服务器)解决问题的方式。

架构 🏗️

我的目标是拥有一个专业的生产环境:

  • 前端: 一个基于 React Dashboard(Vite)的界面,部署在 app.geoengine.dev
  • 后端: 一个使用 Go(Chi Router + PostGIS)的 API,部署在 api.geoengine.dev
  • 安全: 为两个子域名自动提供 HTTPS。
  • 基础设施: 所有内容均使用 Docker 容器化。

与其将端口 80805173 暴露给外部,我使用 Caddy 作为入口。Caddy 充当反向代理,自动处理 SSL 证书的生成和续订。

“魔法” Caddyfile ✨

如果你曾经为 nginx.conf 文件头疼不已,那么你一定会喜欢这个。这正是我为两个子域名启用 HTTPS 所需的全部配置:

# The Dashboard (Frontend)
app.geoengine.dev {
    reverse_proxy dashboard:80
}

# The API (Backend)
api.geoengine.dev {
    reverse_proxy api:8080
}

Caddy 会自动检测域名,向 Let’s Encrypt 申请证书,并完成流量路由。无需 cron 任务,也不需要手动续期。

Docker 设置 🐳

这里是我的 docker-compose.yml 中的秘密配方。请注意,服务不向主机机器暴露端口(Caddy 除外);它们只在 geo-net 网络内部通信。

services:
  # Caddy: The only service exposed to the world
  caddy:
    image: caddy:2-alpine
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
    networks:
      - geo-net
    depends_on:
      - dashboard
      - api

  # Backend API
  api:
    build: ./backend
    expose:
      - "8080" # Only visible to Caddy, not the internet
    environment:
      - ALLOWED_ORIGINS=https://app.geoengine.dev
    networks:
      - geo-net

  # Database
  db:
    image: postgres:15-alpine
    # ... config ...
    networks:
      - geo-net

networks:
  geo-net:
    driver: bridge

挑战(我卡住的地方) 🚧

这并非一路顺风。以下是两个让我花了几个小时调试的“坑”,希望你不必经历同样的痛苦:

1. “孤儿”迁移容器

我使用一个单独的容器来运行数据库迁移(golang-migrate)。它一直因连接错误而崩溃。

解决办法: 即使是工具容器也必须在同一个 Docker 网络中!我忘记在迁移服务里添加 networks: - geo-net,导致它无法“看到”数据库。

2. CORS 恶棍 💀

在本地开发时,允许 *(通配符)进行 CORS 通常可以工作。但一旦我在使用 HTTPS 的生产环境中部署,前端请求就开始失败。浏览器在安全环境下对凭证(cookie/headers)非常严格。我不得不停止懒惰,使用 rs/cors 库在 Go 代码中明确指定确切的来源。

In Go:

// Don't do this in production:
// AllowedOrigins: []string{"*"} // ❌

// Do this instead:
AllowedOrigins: []string{"https://app.geoengine.dev"} // ✅

通过匹配前端的精确来源,浏览器(以及安全协议)才会满意。

结果

在推送更改后,我运行了 docker compose up -d。大约 30 秒后,Caddy 就为我的站点启用了 HTTPS。

您可以在此查看实时演示:https://app.geoengine.dev
或在 GitHub 上浏览代码:Geo Engine Core

如果您正在部署一个副项目,试试 Caddy。它的感觉像是作弊,但却是最好的那种作弊。

祝编码愉快!

0 浏览
Back to Blog

相关文章

阅读更多 »