硬核实践:Docker 部署 Nginx 生产级实战 从基础启动到 HTTPS 反向代理全链路指南

写这篇文章的直接原因:网上搜 Docker 装 Nginx 的教程,十篇有九篇都是 docker run 一下就完事,看起来简单,真到生产环境一用全是坑 ------ 配置文件丢了、日志没持久化、证书挂了、升级容器把站点搞没了。
这篇是我自己踩过坑之后整理的完整生产级部署方案,从基础启动到 Compose 编排,从 HTTP 到 HTTPS,从反向代理到性能调优,从常用命令到排错指南,一条线拉通。
你能从这篇文章得到什么:

  • 三种部署方式的完整命令,复制就能用
  • 生产环境目录结构规范,照着搭就行
  • HTTPS + HTTP/2 完整配置,含证书自动续期
  • 反向代理 + WebSocket 支持的标准写法
  • 常见问题排查清单,遇到问题直接查

适合谁看:

  • 刚接触 Docker,想把 Nginx 跑起来的新手
  • 一直在裸机装 Nginx,想容器化迁移的运维
  • 会基础用法,但想搞清楚生产环境最佳实践的开发者

不废话,直接上干货。

一、环境准备

1.1 系统要求

bash 复制代码
# 检查 Docker 版本
docker --version
# Docker version 24.0.7, build afdd53b

# 检查 Docker Compose 版本
docker compose version
# Docker Compose version v2.21.0

注意:本文基于 Docker 24.x + Compose v2 编写,低于 20.10 版本部分命令可能不兼容。

1.2 前置检查

bash 复制代码
# 确认 Docker 服务正常运行
systemctl status docker

# 确认 80/443 端口未被占用
netstat -tlnp | grep -E ':(80|443)\s'
# 或
ss -tlnp | grep -E ':(80|443)\s'

如果端口被占用,要么停掉占用进程,要么换端口映射。


二、方式一:基础快速启动(适合测试)

2.1 拉取官方镜像

bash 复制代码
# 拉取最新稳定版
docker pull nginx:latest

# 推荐:指定明确版本,生产环境不要用 latest
docker pull nginx:1.27-alpine

# 查看本地镜像
docker images | grep nginx

选型建议

  • nginx:alpine --- 体积小(~40MB),适合生产
  • nginx:latest --- 基于 Debian,体积大(~140MB),调试工具全
  • nginx:stable-alpine --- 稳定分支 + alpine,生产首选

2.2 启动容器

bash 复制代码
docker run -d \
  --name nginx \
  -p 80:80 \
  --restart=always \
  nginx:1.27-alpine

参数说明:

参数 作用
-d 后台运行
--name nginx 容器命名为 nginx
-p 80:80 宿主机 80 端口映射到容器 80 端口
--restart=always Docker 重启后容器自动启动

2.3 验证

bash 复制代码
# 查看容器状态
docker ps | grep nginx

# 浏览器访问或 curl 测试
curl -I http://localhost
# HTTP/1.1 200 OK
# Server: nginx/1.27.0

看到 Welcome to nginx! 就说明跑通了。


三、方式二:挂载配置 + 数据卷(生产标准姿势)

基础启动只能用默认配置,生产环境必须挂载配置文件和静态资源。

3.1 目录结构规划

bash 复制代码
# 创建 Nginx 相关目录
mkdir -p /data/nginx/{conf,conf.d,html,logs,ssl,cert}

目录说明:

目录 用途
/data/nginx/conf 主配置文件 nginx.conf
/data/nginx/conf.d 站点配置,按域名拆分
/data/nginx/html 静态网站根目录
/data/nginx/logs 访问日志 + 错误日志
/data/nginx/ssl SSL 证书存放

3.2 从容器拷贝默认配置

不要自己从零写配置,先从官方镜像里拷出来再改:

bash 复制代码
# 先临时启动一个容器
docker run --name nginx-tmp -d nginx:1.27-alpine

# 拷贝主配置文件
docker cp nginx-tmp:/etc/nginx/nginx.conf /data/nginx/conf/

# 拷贝 conf.d 目录
docker cp nginx-tmp:/etc/nginx/conf.d/default.conf /data/nginx/conf.d/

# 拷贝默认 html 页面
docker cp nginx-tmp:/usr/share/nginx/html /data/nginx/

# 删掉临时容器
docker rm -f nginx-tmp

3.3 主配置文件 nginx.conf

bash 复制代码
user  nginx;
worker_processes  auto;   # 自动匹配 CPU 核心数

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections  10240;   # 调大连接数
    use epoll;                    # Linux 高效 IO 模型
    multi_accept on;              # 一次接受多个连接
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;

    keepalive_timeout  65;

    gzip  on;                     # 开启 gzip 压缩
    gzip_vary on;
    gzip_min_length 1k;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/javascript application/json application/javascript application/xml;

    include /etc/nginx/conf.d/*.conf;   # 加载所有站点配置
}

3.4 站点配置示例

/data/nginx/conf.d/default.conf

bash 复制代码
server {
    listen       80;
    server_name  localhost;

    root   /usr/share/nginx/html;
    index  index.html index.htm;

    # 静态资源缓存
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2?)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # 禁止访问隐藏文件
    location ~ /\. {
        deny all;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

3.5 正式启动容器

bash 复制代码
docker run -d \
  --name nginx \
  -p 80:80 \
  -p 443:443 \
  --restart=always \
  -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf:ro \
  -v /data/nginx/conf.d:/etc/nginx/conf.d:ro \
  -v /data/nginx/html:/usr/share/nginx/html:ro \
  -v /data/nginx/logs:/var/log/nginx \
  -v /data/nginx/ssl:/etc/nginx/ssl:ro \
  --network web-network \
  nginx:1.27-alpine

关键点

  • :ro 表示只读挂载,配置文件建议只读,防止容器内误改
  • 日志目录不要加 :ro,容器需要写权限
  • --network 建议自定义网络,方便和其他容器(如后端服务)内部通信

3.6 配置热重载

改完配置不用重启容器,直接 reload:

bash 复制代码
# 测试配置语法是否正确(必做!)
docker exec nginx nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

# 热重载配置
docker exec nginx nginx -s reload

铁律 :改完配置先 nginx -t,没问题再 reload,直接 reload 可能把服务搞挂。


四、方式三:Docker Compose 部署(推荐)

生产环境统一用 Compose 管理,方便维护和迁移。

4.1 docker-compose.yml

bash 复制代码
version: '3.8'

services:
  nginx:
    image: nginx:1.27-alpine
    container_name: nginx
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./conf.d:/etc/nginx/conf.d:ro
      - ./html:/usr/share/nginx/html:ro
      - ./logs:/var/log/nginx
      - ./ssl:/etc/nginx/ssl:ro
    networks:
      - web-network
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://localhost/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 5s

networks:
  web-network:
    driver: bridge

4.2 启动

bash 复制代码
# 前台启动看日志
docker compose up

# 后台启动
docker compose up -d

# 查看状态
docker compose ps

# 查看日志
docker compose logs -f nginx

五、HTTPS 配置(Let's Encrypt 免费证书)

5.1 申请证书(certbot)

bash 复制代码
# 安装 certbot
apt install certbot -y   # Debian/Ubuntu
# 或
yum install certbot -y   # CentOS

# 手动模式申请(需要在域名 DNS 加 TXT 记录验证)
certbot certonly --manual --preferred-challenges dns -d yourdomain.com

证书生成位置:/etc/letsencrypt/live/yourdomain.com/

5.2 Nginx HTTPS 配置

/data/nginx/conf.d/yourdomain.conf

bash 复制代码
server {
    listen 80;
    server_name yourdomain.com;
    # HTTP 强制跳转 HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    # SSL 安全配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # HSTS
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

5.3 证书续期

Let's Encrypt 证书有效期 90 天,设置定时任务自动续期:

bash 复制代码
# 测试续期
certbot renew --dry-run

# 添加 crontab,每天凌晨 2 点检查续期
crontab -e
# 0 2 * * * certbot renew --quiet --deploy-hook "docker exec nginx nginx -s reload"

六、反向代理配置(最常用场景)

6.1 代理到后端服务

bash 复制代码
server {
    listen 80;
    server_name api.yourdomain.com;

    location / {
        proxy_pass http://backend-service: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_connect_timeout 60s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;

        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

注意proxy_pass 里的 backend-service 是容器名,前提是 Nginx 和后端服务在同一个 Docker network 里。


七、常用运维命令

7.1 容器操作

bash 复制代码
# 启动/停止/重启
docker start nginx
docker stop nginx
docker restart nginx

# 进入容器
docker exec -it nginx sh    # alpine 用 sh,不用 bash

# 查看实时日志
docker logs -f nginx
docker logs -f --tail 100 nginx   # 只看最后 100 行

# 查看资源占用
docker stats nginx

7.2 Nginx 内部命令

bash 复制代码
# 查看版本
docker exec nginx nginx -v

# 查看编译参数
docker exec nginx nginx -V

# 测试配置
docker exec nginx nginx -t

# 热重载
docker exec nginx nginx -s reload

# 优雅退出
docker exec nginx nginx -s quit

7.3 日志分析

bash 复制代码
# 实时看访问日志
tail -f /data/nginx/logs/access.log

# 统计 TOP 10 IP
awk '{print $1}' /data/nginx/logs/access.log | sort | uniq -c | sort -rn | head -10

# 统计 404 数量
grep ' 404 ' /data/nginx/logs/access.log | wc -l

八、常见问题与排错

Q1:容器启动后立即退出

bash 复制代码
# 查看退出原因
docker logs nginx

大概率是配置文件语法错误,先 nginx -t 检查。

Q2:403 Forbidden

常见原因:

  • 目录没有 index 文件
  • 文件权限问题(容器内 nginx 用户 uid=101)
  • SELinux 限制(CentOS 常见)
bash 复制代码
# 修复权限
chmod -R 755 /data/nginx/html
chown -R 101:101 /data/nginx/html   # alpine 镜像 nginx uid 是 101

Q3:502 Bad Gateway

反向代理场景常见,后端服务没起来或网络不通:

bash 复制代码
# 检查后端容器是否在同一网络
docker network inspect web-network

# 从 nginx 容器里 ping 后端
docker exec nginx wget -qO- http://backend-service:8080/health

Q4:上传文件 413 Request Entity Too Large

Nginx 默认限制请求体大小 1MB,在 serverlocation 块加:

bash 复制代码
client_max_body_size 50M;

九、性能优化建议

  1. worker_processes auto --- 自动匹配 CPU 核心数
  2. worker_connections 调大 --- 根据服务器内存设,一般 10240 起步
  3. 开启 gzip --- 文本类资源压缩率 60%+
  4. 静态资源缓存 --- 图片、CSS、JS 设长缓存
  5. 开启 sendfile + tcp_nopush --- 减少内核态用户态切换
  6. 日志缓冲 --- 高并发场景 access_logbuffer=64k flush=5s
  7. 使用 HTTP/2 --- HTTPS 下开启 http2 多路复用

总结

Docker 部署 Nginx 三步走:

  1. 测试环境 :直接 docker run 快速起一个
  2. 生产环境:目录挂载 + 配置外置 + 数据卷持久化
  3. 规范管理:Docker Compose 编排 + 健康检查 + 自定义网络

核心原则:配置文件外置、日志持久化、版本号固定、改配置先 -t 再 reload


CSDN 标签(Tags)Docker Nginx Docker Compose 反向代理 HTTPS 运维 容器化 Linux 部署 性能优化

关键词: Docker 安装 Nginx、Docker Nginx 教程、Nginx 反向代理 Docker、Docker Compose Nginx、Nginx HTTPS 配置、Docker Nginx 挂载配置、容器化部署、Nginx 性能优化

完成硬核CSDN风格Docker安装NGINX文章

已输出完整硬核 CSDN 风格教程,核心要点速览:

三种部署方式

  • 快速测试:docker run 直接起,适合临时验证
  • 生产标准:目录挂载 + 配置外置 + 数据卷持久化(confconf.dhtmllogsssl 五个目录)
  • 规范管理:Docker Compose 编排 + 健康检查 + 自定义网络

核心操作铁律

  • 镜像版本固定,生产别用 latest,推荐 nginx:1.27-alpine
  • 改配置先 nginx -t 验证,没问题再 nginx -s reload
  • 配置文件加 :ro 只读挂载,防止容器内误改

常见坑

  • 403:文件权限问题,alpine 镜像 nginx uid 是 101
  • 502:后端容器不在同一 network
  • 413:默认请求体 1MB,需加 client_max_body_size