自定义域名 #

域名概述 #

Heroku 应用默认使用 app-name.herokuapp.com 域名,你可以添加自定义域名使应用更专业。

域名类型 #

类型 说明 示例
根域名 顶级域名 example.com
子域名 二级域名 www.example.com, api.example.com
通配符域名 匹配所有子域名 *.example.com

添加域名 #

使用 CLI 添加 #

bash
# 添加域名
heroku domains:add www.example.com

# 添加根域名
heroku domains:add example.com

# 添加通配符域名
heroku domains:add *.example.com

# 指定应用
heroku domains:add www.example.com --app myapp

查看域名 #

bash
# 查看所有域名
heroku domains

# 输出示例
# === myapp Domain Names
# Domain Name      DNS Target
# ───────────────  ──────────────────────────────
# example.com      hidden-lake-12345.herokudns.com
# www.example.com  hidden-lake-12345.herokudns.com

删除域名 #

bash
# 删除域名
heroku domains:remove www.example.com

# 删除所有域名
heroku domains:clear

DNS 配置 #

DNS 记录类型 #

text
┌─────────────────────────────────────────────────────┐
│              DNS 记录配置                            │
├─────────────────────────────────────────────────────┤
│                                                     │
│  子域名 (www.example.com)                           │
│  ┌─────────────────────────────────────────────┐   │
│  │  类型: CNAME                                 │   │
│  │  名称: www                                   │   │
│  │  值: hidden-lake-12345.herokudns.com        │   │
│  └─────────────────────────────────────────────┘   │
│                                                     │
│  根域名 (example.com)                               │
│  ┌─────────────────────────────────────────────┐   │
│  │  方式一: ALIAS/ANAME (推荐)                  │   │
│  │  类型: ALIAS                                 │   │
│  │  值: hidden-lake-12345.herokudns.com        │   │
│  │                                              │   │
│  │  方式二: A 记录                              │   │
│  │  类型: A                                     │   │
│  │  值: 76.76.21.21                            │   │
│  └─────────────────────────────────────────────┘   │
│                                                     │
└─────────────────────────────────────────────────────┘

DNS 配置示例 #

text
# Cloudflare DNS 配置

# 子域名
Type: CNAME
Name: www
Target: hidden-lake-12345.herokudns.com
Proxy: 关闭(SSL 验证需要)

# 根域名
Type: CNAME (Flattening)
Name: @
Target: hidden-lake-12345.herokudns.com

# 或使用 A 记录
Type: A
Name: @
Target: 76.76.21.21

DNS 验证 #

bash
# 检查 DNS 解析
dig www.example.com

# 或使用 nslookup
nslookup www.example.com

# 检查 DNS 目标
heroku domains

SSL 证书 #

自动 SSL #

Heroku 自动为自定义域名提供免费的 SSL 证书(ACM)。

bash
# 查看证书状态
heroku certs

# 输出示例
# === myapp SNI Endpoints
# Certificate Details:
# Common Name(s): www.example.com
#                example.com
# Expires At:     2025-01-15 00:00 UTC
# Issuer:         Let's Encrypt
# Starts At:      2024-01-15 00:00 UTC
# Subject:        CN=www.example.com
# Trusted:        True

SSL 状态 #

状态 说明
Pending 正在验证
Verified 验证成功
Failed 验证失败

SSL 故障排查 #

bash
# 如果 SSL 验证失败
# 1. 检查 DNS 配置
dig www.example.com

# 2. 确保 DNS 指向 Heroku DNS Target
heroku domains

# 3. 等待 DNS 传播(可能需要 24-48 小时)

# 4. 重新验证
heroku certs:auto:enable

自定义 SSL 证书 #

bash
# 上传自定义证书
heroku certs:add server.crt server.key

# 更新证书
heroku certs:update server.crt server.key

# 查看证书信息
heroku certs:info

# 删除证书
heroku certs:remove

域名路由 #

多域名路由 #

javascript
// Express.js 多域名路由
const express = require('express');
const app = express();

app.use((req, res, next) => {
  const host = req.get('host');
  
  if (host === 'api.example.com') {
    // API 路由
    return apiRouter(req, res, next);
  } else if (host === 'admin.example.com') {
    // 管理后台路由
    return adminRouter(req, res, next);
  }
  
  // 默认路由
  next();
});

域名重定向 #

javascript
// 重定向 www 到非 www
app.use((req, res, next) => {
  const host = req.get('host');
  
  if (host.startsWith('www.')) {
    const newHost = host.slice(4);
    return res.redirect(301, `${req.protocol}://${newHost}${req.originalUrl}`);
  }
  
  next();
});

// 强制 HTTPS
app.use((req, res, next) => {
  if (req.header('x-forwarded-proto') !== 'https') {
    return res.redirect(301, `https://${req.header('host')}${req.url}`);
  }
  next();
});

通配符域名 #

配置通配符域名 #

bash
# 添加通配符域名
heroku domains:add *.example.com

# DNS 配置
# Type: CNAME
# Name: *
# Target: hidden-lake-12345.herokudns.com

动态子域名处理 #

javascript
// 处理动态子域名
app.use((req, res, next) => {
  const host = req.get('host');
  const subdomain = host.split('.')[0];
  
  if (subdomain && subdomain !== 'www') {
    req.subdomain = subdomain;
  }
  
  next();
});

// 子域名路由
app.get('/', (req, res) => {
  if (req.subdomain) {
    // 处理子域名请求
    return handleSubdomain(req, res);
  }
  
  // 处理主域名请求
  res.render('home');
});

域名最佳实践 #

1. 同时配置 www 和非 www #

bash
# 添加两个域名
heroku domains:add example.com
heroku domains:add www.example.com

# 在应用中处理重定向

2. DNS 配置检查清单 #

markdown
## DNS 配置检查
- [ ] CNAME 记录指向 Heroku DNS Target
- [ ] 根域名使用 ALIAS 或 A 记录
- [ ] DNS 代理已关闭(SSL 验证期间)
- [ ] TTL 设置合理(建议 300-3600)

3. SSL 配置检查清单 #

markdown
## SSL 配置检查
- [ ] DNS 已正确解析
- [ ] 自动 SSL 已启用
- [ ] 证书状态为 Verified
- [ ] 强制 HTTPS 已配置

故障排查 #

域名无法访问 #

bash
# 1. 检查域名是否添加
heroku domains

# 2. 检查 DNS 解析
dig www.example.com

# 3. 检查应用状态
heroku ps

# 4. 检查日志
heroku logs --tail

SSL 证书错误 #

bash
# 检查证书状态
heroku certs

# 如果状态为 Failed
# 1. 检查 DNS 配置
# 2. 确保没有代理
# 3. 重新启用自动 SSL
heroku certs:auto:enable

DNS 传播延迟 #

bash
# 使用在线工具检查 DNS 传播
# https://dnschecker.org

# 或使用 dig 检查不同 DNS 服务器
dig @8.8.8.8 www.example.com
dig @1.1.1.1 www.example.com

下一步 #

自定义域名掌握后,接下来学习 Heroku CI 了解持续集成!

最后更新:2026-03-28