这次我们来把 Docker 和 Nginx 放在同一条链路里讲清楚:用 Docker 装服务、用 Nginx 做统一入口、用 upstream 做负载均衡。这套组合在个人项目、中小项目上线和本地开发里几乎绕不开,比单纯装一个 LAMP/LNMP 环境要灵活得多。
先说结论:如果你希望多个服务不再靠端口号硬记,不如让 Nginx 按域名和路径自动转发;如果你担心环境不一致、依赖冲突,不如把 MySQL、Redis、后端 API、前端页面全部用 docker compose 管理。这篇文章不要求你必须有现成的云服务器,Windows 或 Linux 都可以跟着跑,重点是让你掌握容器部署、反向代理、负载均衡三个环节的落地方法。
文章会覆盖这些内容:Docker 安装与常用命令、docker compose 多服务编排、Nginx 静态站点、多站点反向代理、HTTPS 证书加载、WebSocket 转发、Ollama 这类 API 服务的代理、upstream 负载均衡,最后是一批常见报错的排查方向和工程化建议。读完至少能回答三个问题:服务怎么装进容器、流量怎么统一收到 Nginx、多个后端实例怎么分摊请求。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 技术组合 | Docker 容器部署 + Nginx 反向代理 + 负载均衡 |
| 主要功能 | 容器创建与编排、静态站点托管、域名反代、HTTPS 证书、WebSocket 转发、多后端负载均衡 |
| 推荐硬件 | 最低 4GB 内存、20GB 磁盘;生产环境按服务规模评估 |
| 支持平台 | Linux、Windows(WSL2 / Docker Desktop)、macOS |
| 启动方式 | docker 命令、docker compose、Nginx 配置文件 |
| 接口能力 | Nginx 支持 HTTP/HTTPS/WebSocket/TCP 代理;容器内服务可暴露 REST API |
| 批量任务 | docker compose 可批量启停服务;Nginx upstream 可将请求分发给多个后端实例 |
| 适合场景 | 个人站点、前后端分离项目、多站点服务器、AI 模型 API 代理、单机负载均衡 |
这里要说明一句:Docker 本身不是虚拟机,它是容器运行时;Nginx 也不是全套网关,但它能覆盖绝大多数中小项目的入口需求。两者结合后,最常见的形态就是“一套 docker compose 管理所有服务,一个 Nginx 容器接收外部流量”。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 适用场景与使用边界
2.1 这套组合适合谁
如果你属于下面几类,这套组合可以直接套用:
- 个人开发者:一台云服务器上想同时跑博客、API、数据库,不希望所有端口都暴露在公网。
- 前后端分离项目:前端静态文件交给 Nginx,
/api请求反向代理到后端容器。 - 本地开发环境:需要快速启动 MySQL、Redis、Ollama、后端服务,一条命令完成依赖拉起。
- 多站点运维:一台服务器上多个域名,用 Nginx 的
server_name分流。 - 单机负载均衡:同一套应用启动多个实例,用 Nginx upstream 做请求分发和简单故障转移。
2.2 不适合什么场景
- 需要跨多台服务器的容器调度,Docker 单机能力不够,一般要引入 Kubernetes 或云托管平台。
- 需要主动健康检查的负载均衡,Nginx 开源版只有被动检查,主动探测要依赖 Nginx Plus、第三方模块或云负载均衡产品。
- 需要极低的网络转发延迟,Nginx 本身性能很好,但对比内核态 LB 还是存在用户态转发损耗,超高并发场景建议分层。
2.3 合规与安全边界
使用 Docker 镜像时,只使用你有权使用的官方镜像或可信镜像;代理 AI 服务时要注意 API Key 保护,不要直接把没有鉴权的 Ollama 或后端服务暴露到公网;HTTPS 证书要使用合法渠道申请,本地测试可用自签名证书,生产环境不要使用不受信任的证书。反向代理不是用来绕过访问控制的,所有服务都应保持自身的认证和授权机制。
3. 环境准备与前置条件
3.1 系统要求
Linux 是 Docker 最顺的环境,推荐 Ubuntu、Debian、CentOS 等主流发行版;Windows 需要 Windows 10/11 64 位,并开启 WSL2 或 Hyper-V;macOS 可以直接使用 Docker Desktop。Nginx 容器本身非常轻,但 MySQL、Redis、业务服务会占资源,建议主机内存至少 4GB,磁盘预留 20GB 以上。
3.2 Windows 专属检查项
Windows 上安装 Docker Desktop 最容易遇到的问题就是启动时报类似 virtualisation support wasn't detected。出现这个报错,按顺序排查:
- 打开任务管理器,切到“性能”标签,在 CPU 栏目里检查“虚拟化”是否显示“已启用”。
- 如果未启用,重启电脑,进入 BIOS/UEFI 设置,打开 Intel VT-x 或 AMD-V,保存退出。
- 在 Windows 功能中开启“虚拟机平台”和“适用于 Linux 的 Windows 子系统”。
- 检查 WSL2 内核是否正常,必要时用系统的“启用或关闭 Windows 功能”重新安装 WSL 组件。
- 确认没有旧版 Docker Toolbox 残留,有则先卸载再装 Docker Desktop。
3.3 端口规划
Docker 把容器端口映射到宿主机时,最容易出现端口冲突。建议先做一张规划表:
| 服务 | 默认端口 | 说明 |
|---|---|---|
| Nginx | 80 / 443 | 对外开放入口 |
| 后端 API | 8000 / 8080 | 尽量只暴露到容器网络,或仅绑定 127.0.0.1 |
| MySQL | 3306 | 避免公网直接暴露,只对内部网络开放 |
| Redis | 6379 | 同上,禁止裸奔到 0.0.0.0 |
| Ollama | 11434 | 通过 Nginx 加鉴权后代理 |
4. Docker 安装与服务启动
4.1 Linux 安装 Docker
Linux 安装 Docker 有多种方式,这里给一个通用做法:下载官方安装脚本,然后交给系统安装。实际使用前请确认你已经看过脚本内容,或直接参考 Docker 官方文档。
bash复制curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo systemctl enable --now docker
docker version
安装完成后,如果不想每次输 sudo,可以把当前用户加入 docker 组,然后重新登录终端。
bash复制sudo usermod -aG docker $USER
newgrp docker
docker info
注意:加入 docker 组本质上是将用户提升为等同于 root 的权限,只建议在可信任的服务器上这样做。
4.2 启动第一个 Nginx 容器
先跑一个最简 Nginx 容器,确认 Docker 环境可用。
bash复制docker run -d --name nginx-test -p 80:80 nginx:alpine
docker ps
curl http://127.0.0.1
解释一下这条命令:-d 表示后台运行,--name nginx-test 是容器名,-p 80:80 把宿主机 80 端口映射到容器 80 端口。curl 返回 Nginx 默认欢迎页,说明容器启动成功。
查看日志和进入容器:
bash复制docker logs nginx-test
docker exec -it nginx-test sh
进去之后可以看看 /etc/nginx/conf.d 和 /usr/share/nginx/html 的目录结构。后面所有配置修改,都是围绕这两个目录展开。
4.3 使用 docker compose 管理服务
裸 docker run 适合单容器测试,服务一多,维护困难。更常见的方式是 docker compose。先用命令创建目录结构:
bash复制mkdir -p ~/stack-demo/{nginx/conf.d,html,cert,logs}
cd ~/stack-demo
然后写一个最基础的 docker-compose.yml:
yaml复制services:
nginx:
image: nginx:alpine
container_name: nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./html:/usr/share/nginx/html:ro
- ./cert:/etc/nginx/cert:ro
- ./logs:/var/log/nginx
启动并观察状态:
bash复制docker compose up -d
docker compose ps
docker compose logs -f
有个细节需要注意:如果宿主机 ./nginx/conf.d 是空目录,挂载到容器 /etc/nginx/conf.d 后,镜像里默认的 default.conf 会被覆盖,Nginx 可能不再有可用站点。因此挂载后要在 nginx/conf.d 下补一个配置文件,例如 default.conf:
nginx复制server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
}
}
再往 html 目录放一个 index.html,重新 docker compose restart nginx,页面就能正常访问。这个“空目录覆盖导致配置丢失”的问题,后面排查章节还会提到。
5. 容器部署示例:MySQL、Redis、后端应用
5.1 用 compose 部署后端和 MySQL
不要在 conf.d 里写死数据库 IP,更合理的方式是把多个服务放进同一个 compose 网络,用服务名互通。下面是一个精简示例,同时包含 Nginx、后端应用和 MySQL:
yaml复制services:
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./html:/usr/share/nginx/html:ro
networks:
- frontend
- backend
depends_on:
- app
app:
image: your-app-image:latest
environment:
DB_HOST: mysql
DB_USER: app
DB_PASSWORD: change-me-app
networks:
- backend
depends_on:
- mysql
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: change-me
MYSQL_DATABASE: app
MYSQL_USER: app
MYSQL_PASSWORD: change-me-app
volumes:
- mysql-data:/var/lib/mysql
networks:
- backend
networks:
frontend:
backend:
volumes:
mysql-data:
要点是:Nginx 与 app 同时处于 backend 网络,所以 Nginx 配置文件里可以直接写 proxy_pass http://app:8080;,app 通过服务名 mysql 访问数据库。MySQL 的端口没有映射到宿主机,只有同一网络内的服务能访问,比直接暴露 3306 安全得多。
5.2 部署 Redis
如果需要缓存或队列,可以在 compose 里加一个 Redis 服务:
yaml复制services:
redis:
image: redis:7-alpine
command: ["redis-server", "--appendonly", "yes"]
volumes:
- redis-data:/data
networks:
- backend
ports:
- "127.0.0.1:6379:6379"
volumes:
redis-data:
127.0.0.1:6379:6379 这种写法只把端口绑定到本机回环,外部网络访问不到。本地调试时可以用本机客户端连,其他服务在 Docker 网络里再用服务名 redis 访问。
5.3 静态站点
静态站点的更新很简单,把文件放到 html 目录,Nginx 配置里指向 /usr/share/nginx/html,再 reload 即可:
bash复制docker exec nginx nginx -s reload
这套流程比直接修改宿主机 Nginx 目录更干净,因为所有依赖和目录结构都记录在 compose 文件里,换机器只需要复制项目目录再 docker compose up -d。
6. Nginx 反向代理配置
6.1 反向代理做了什么
反向代理是“客户端访问 Nginx,Nginx 再把请求转发给内部服务”。外部用户只看到 Nginx 的 80/443 端口,看不到后端服务的真实端口,也看不到 MySQL、Redis 的存在。这样做的好处很多:域名可以共用同一端口、后端可以随时迁移、TLS 证书集中管理、还能在 Nginx 层做访问控制和超时控制。
6.2 最基本的反向代理配置
在 nginx/conf.d 下新建 api.conf,把 / 转发到 app 容器:
nginx复制server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://app:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
重点是 proxy_pass http://app:8080;,这里的 app 是 compose 里的服务名,Nginx 容器会通过 Docker 内置 DNS 解析到 app 容器地址。如果后端不在 Docker 网络里,也可以换成 http://127.0.0.1:8080;。
修改完配置后测试并重载:
bash复制docker exec nginx nginx -t
docker exec nginx nginx -s reload
检查语法通过再 reload,是避免线上事故的基本操作。
6.3 路径转发与去除前缀
很多项目习惯把 API 放在 /api 路径下,Nginx 配置可以只代理 /api:
nginx复制location /api/ {
proxy_pass http://app:8080/;
proxy_set_header Host $host;
}
这里注意斜杠的区别:proxy_pass 结尾带 /,会把 location 匹配到的 /api/ 前缀去掉后再转发;如果不带 /,转发时保留完整 URI。具体行为依赖后端接口设计,建议先在接口文档里确认路由规则,再决定是否保留前缀。
6.4 多站点配置
一台服务器想跑多个域名,可以用多个 server 块对应不同 server_name:
nginx复制server {
listen 80;
server_name site1.example.com;
location / {
proxy_pass http://127.0.0.1:8081;
}
}
server {
listen 80;
server_name site2.example.com;
location / {
proxy_pass http://127.0.0.1:8082;
}
}
也可以把两个站点拆成 site1.conf 和 site2.conf 两个文件放在 conf.d 目录下。Nginx 启动时会读取 /etc/nginx/conf.d/*.conf,目录结构更清晰。注意:客户端必须能正确解析域名,本地测试可以把域名写到 hosts 文件里,把域名解析到 127.0.0.1。
6.5 HTTPS 与证书加载
容器启动时已经挂载了 ./cert:/etc/nginx/cert:ro,证书和私钥放在宿主机 cert 目录,Nginx 配置里直接引用容器内路径即可:
nginx复制server {
listen 443 ssl;
server_name app.example.com;
ssl_certificate /etc/nginx/cert/app.example.com.pem;
ssl_certificate_key /etc/nginx/cert/app.example.com.key;
location / {
proxy_pass http://app:8080;
proxy_set_header Host $host;
}
}
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
修改证书后不需要重新创建容器,执行 docker exec nginx nginx -s reload 即可。如果访问仍然显示旧证书,先检查浏览器缓存,再用下面的命令确认实际返回的证书:
bash复制openssl s_client -connect app.example.com:443 -servername app.example.com
6.6 WebSocket 反向代理
很多实时应用需要 WebSocket,Nginx 默认不识别升级协议,需要显式配置:
nginx复制location /ws/ {
proxy_pass http://app:8080/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
如果不加 Upgrade 和 Connection,客户端连接可能一直无法建立,或者建立后很快断开。
6.7 代理 Ollama 等 AI 服务
Ollama 默认监听 11434 端口,而且没有内置鉴权。如果直接把端口暴露到公网,任何人都能调用你的模型服务。更稳妥的做法是通过 Nginx 加 Basic Auth,并限制可访问的来源 IP。
nginx复制server {
listen 80;
server_name ollama.example.com;
location / {
proxy_pass http://127.0.0.1:11434;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/conf.d/htpasswd;
}
}
生成密码文件可以参考下面的命令,再把生成结果写入 htpasswd:
bash复制openssl passwd -apr1 -stdin
输入密码后,把输出和用户名组合成一行,例如 user:$apr1$xxxxyyyy...,放到 nginx/conf.d/htpasswd。生产环境建议在 Nginx 层之外再加一层 API Key 校验,避免口令泄露造成损失。
7. 负载均衡配置
7.1 先准备两个后端
负载均衡可以先从两个本地容器开始测试。假设有两个后端服务,分别监听 8080 和 8081 端口:
bash复制docker run -d --name web1 -p 8080:80 nginx:alpine
docker run -d --name web2 -p 8081:80 nginx:alpine
docker exec web1 sh -c "echo 'backend 1' > /usr/share/nginx/html/index.html"
docker exec web2 sh -c "echo 'backend 2' > /usr/share/nginx/html/index.html"
真实项目里这两个端口就是两个应用实例,这里用 Nginx 容器模拟,只是为了验证负载均衡是否生效。
7.2 配置 upstream
在 Nginx 的 conf.d 里新建 lb.conf:
nginx复制upstream demo_backend {
server 127.0.0.1:8080 weight=1;
server 127.0.0.1:8081 weight=1;
}
server {
listen 80;
server_name lb.example.com;
location / {
proxy_pass http://demo_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
在本机 hosts 文件里把 lb.example.com 指向 127.0.0.1,然后连续请求多次:
bash复制for i in $(seq 1 10); do curl http://lb.example.com; done
如果配置正确,会看到 backend 1 和 backend 2 交替出现。默认是轮询策略,每个新连接会按顺序转发到下一个后端。
7.3 负载均衡策略
Nginx upstream 支持的常见策略:
- 默认轮询:请求平均分发到每个后端。
- weight:按权重分配,权重越高,被分到的概率越大。
- ip_hash:按客户端 IP 哈希,同一个 IP 尽量固定到同一后端。
- least_conn:将请求转发到当前连接数最少的后端。
示例:
nginx复制upstream app_backend {
ip_hash;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
如果应用依赖 Session 且没有集中式 Session 存储,先用 ip_hash 可以缓解会话丢失问题,但长期方案还是把 Session 放到 Redis 等共享存储中。
7.4 失败转移与被动健康检查
upstream 里的 max_fails 和 fail_timeout 可以控制故障转移行为:
nginx复制upstream app_backend {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
}
当后端在 fail_timeout 内连续失败 max_fails 次,Nginx 会在一段时间内不再把请求分给它。这是被动健康检查,不是主动探测。要主动探测后端存活,需要 Nginx Plus 或额外模块,开源版本通常依赖外部监控系统辅助判断。
7.5 upstream keepalive
如果短连接请求量很大,可以在 upstream 里配置 keepalive,减少上游连接的重复建立:
nginx复制upstream app_backend {
server 127.0.0.1:8080;
keepalive 16;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
使用 Connection "" 让 Nginx 与后端之间复用长连接。注意,keepalive 数量不是越大越好,需要根据实际并发数和后端连接数限制来调整。
8. 接口 API 验证与容器编排任务
8.1 通过 Nginx 验证 API
配置完成后,最重要的一步是确认 API 能从外部正常访问。假设后端健康检查接口是 /health,可以执行:
bash复制curl -i http://127.0.0.1/health
期望返回 200 和 JSON 数据。如果返回 502,说明 Nginx 无法连接到后端;如果返回 404,检查路径转发规则是否正确。
8.2 Python 调用示例
后续做自动化脚本时,可以用 Python 请求经过 Nginx 暴露的服务:
python复制import requests
session = requests.Session()
url = "http://127.0.0.1/health"
try:
resp = session.get(url, timeout=5)
print(resp.status_code)
print(resp.json())
except requests.exceptions.RequestException as exc:
print("request failed:", exc)
这只是通用示例,实际接口地址、请求方法、token 字段都要按后端项目的接口文档调整。
8.3 docker compose 批量管理
docker compose 天然适合批量任务场景。一条命令可以启动、停止、重启多个服务,非常适合开发和运维:
bash复制docker compose up -d
docker compose ps
docker compose logs -f --tail=50
docker compose restart nginx
docker compose down
生产环境建议只把 restart 策略设为 unless-stopped,让容器在机器重启后自动恢复。批量维护时,尽量使用 compose 而不是逐个容器操作,避免出现“某个服务忘记映射网络”的问题。
9. 资源占用与性能观察
9.1 用 docker stats 看资源占用
容器运行期间,可以实时查看 CPU、内存、网络和磁盘 IO:
bash复制docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.PIO}}"
Nginx 容器本身资源占用通常很低,真正的内存大户一般是 MySQL、Redis 和业务应用。如果负载均衡后面的某个实例内存飙升,先定位容器再定位代码,不要直接在宿主机上盲目杀进程。
9.2 影响 Nginx 性能的关键参数
Nginx 性能受 worker_processes、worker_connections、日志量、gzip、keepalive 影响较大。一个基础的 nginx.conf 片段如下:
nginx复制worker_processes auto;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
include /etc/nginx/conf.d/*.conf;
}
worker_processes auto 会让 Nginx 按 CPU 核数生成 worker 进程,不要盲目调大。worker_connections 与系统最大文件描述符有关,调高前先确认系统的 ulimit 和内核参数。
9.3 限制容器资源
为了避免某个容器吃光机器内存,可以用 Docker 限制 CPU 和内存:
bash复制docker run -d --name app-demo --memory=512m --cpus=0.5 --restart=unless-stopped myapp
在 compose 里可以写:
yaml复制services:
app:
image: your-app-image:latest
mem_limit: 512m
cpus: 0.5
资源限制不一定能让应用跑得更快,但能避免一个异常服务拖垮整台机器。Nginx 高并发场景下,还要重点观察连接数和文件描述符,不要只盯着 CPU。
10. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| Docker Desktop 启动失败,提示 virtualisation support wasn't detected | BIOS 虚拟化未开启、Hyper-V/WSL2 未启用 | 任务管理器查看虚拟化状态;检查 Windows 功能 | 进入 BIOS 开启 VT-x/AMD-V;开启“虚拟机平台”和 WSL 组件 |
| 拉取镜像超时或很慢 | 网络问题或镜像源不稳定 | 查看 docker pull 报错;测试镜像仓库连通性 |
配置可信镜像加速地址;换网络重试 |
| 容器启动后立即退出 | 启动命令错误、环境变量缺失、端口冲突 | docker logs 容器名 查看日志 |
修正 command 和 environment;调整端口 |
| MySQL 容器启动失败 | 数据目录权限、端口占用、初始化 SQL 问题 | docker logs mysql;检查宿主机 3306 端口 |
确认 MYSQL_ROOT_PASSWORD 等变量;修改端口映射;修卷权限 |
| Docker 容器之间网络不通 | 容器不在同一网络,或服务名解析失败 | docker network inspect;在容器内 ping 服务名 |
把服务加入同一 compose 网络,启动顺序用 depends_on 控制 |
| Nginx 挂载 conf.d 后报错 | 空目录覆盖默认配置、文件权限不对 | docker exec nginx nginx -t;查看挂载路径 |
在宿主机 conf.d 下补齐配置文件,用 :ro 只读挂载 |
| 反向代理返回 502 Bad Gateway | Nginx 无法连接后端、后端未启动、服务名错 | 检查后端日志;在 Nginx 容器内解析服务名 | 修正 proxy_pass 地址;确认后端端口;确认网络一致 |
| 修改 nginx 配置不生效 | 没 reload、挂载路径不对 | 执行 docker exec nginx nginx -t 和 reload |
语法检查后 reload;确认挂载的是 conf.d 而不是其他路径 |
| 替换 SSL 证书不生效 | 浏览器缓存、证书链不完整、没 reload | openssl s_client 检查证书;curl -I https://... |
更新证书后 reload;确保证书和私钥匹配 |
| HTTPS 提示证书名称不匹配 | 证书域名与实际访问域名不一致 | 查看证书 SAN 字段;确认访问域名 | 按域名重新申请证书;本地测试可检查 hosts 映射 |
| 代理接口报 invalid CORS request | 跨域请求头缺失或 Preflight 配置错误 | 用带 Origin 的 curl 复现,查看 OPTIONS 请求 | 在 location 中增加 CORS 响应头和 OPTIONS 处理 |
| API 代理超时 | 上游处理慢、proxy timeout 过短 | 查看上游日志;time curl 统计耗时 | 增大 proxy_read_timeout、proxy_send_timeout |
11. 最佳实践与使用建议
11.1 推荐的项目目录结构
建议把 Docker、Nginx 配置和项目文件分开,目录结构保持可迁移:
code复制project/
├── docker-compose.yml
├── .env
├── nginx/
│ ├── nginx.conf
│ └── conf.d/
│ ├── site1.conf
│ └── site2.conf
├── html/
├── cert/
└── logs/
.env 文件里保存环境变量,例如数据库密码、API Key,不要提交到 Git 仓库。compose 文件里通过 ${VAR} 引用,敏感信息集中在 .env 中管理。
env复制MYSQL_ROOT_PASSWORD=change-me
MYSQL_DATABASE=app
MYSQL_USER=app
MYSQL_PASSWORD=change-me-app
11.2 工程化建议
- 第一次部署先小规模验证,不要直接把生产流量切进来。
- 改配置前先备份,
docker compose down前确认数据卷不会误删。 - 数据库数据放在 volume 或宿主机持久化目录,不要放到容器可写层。
- 所有对外服务都经过 Nginx,数据库和 Redis 不要映射到公网端口。
- 日志要定期轮转,长时间运行的容器会产生大量 access_log 和容器日志。
- 定期清理无用的镜像和容器,
docker system prune -af会删除未被使用的资源,使用前确认没有需要保留的东西。 - 监控很重要,可以用 Zabbix、Prometheus 等工具监控 Nginx 状态、容器资源、端口连通性。Nginx 本身也有
stub_status模块,生产环境建议开启基础访问指标监控。
11.3 合规使用提醒
如果你用这套组合代理 AI 模型、Ollama、后端 API,务必确认服务本身的授权边界,不要把没有鉴权的接口直接暴露到公网。涉及用户数据、人脸、声音、版权素材时,必须在业务层面保证授权和隐私合规,Nginx 配置无法替代法律和业务审核。
12. 总结与下一步
这套 Docker + Nginx 组合最值得尝试的地方,是把“部署一堆服务”变成“一套 compose 文件 + 一个 Nginx 入口”。最先建议验证的功能是:用 docker compose 启动 Nginx 和 MySQL,然后通过 Nginx 反向代理访问后端接口。最容易踩的坑集中在容器网络、空目录挂载覆盖默认配置、证书域名不匹配和端口冲突,这几个问题排查清楚,日常使用就能顺畅很多。
后续可以继续扩展的方向包括:用 Certbot 自动签发和续期 SSL 证书、把 compose 项目接入 CI/CD、给 Nginx 增加访问日志监控和告警、在多台服务器上引入云负载均衡或 Kubernetes。先把单机的容器部署、反向代理和负载均衡跑通,再去碰更高层的编排,思路会更清晰,排查问题也会更容易。
