Skip to content

02 · 安装与第一次启动

生活类比:装 Nginx 就像买一台咖啡机

  • 用 Docker → 网购自动化版(开箱即用,按一下就出咖啡)
  • 用 apt / yum → 楼下电器店(包邮包售后,但版本可能旧)
  • 编译安装 → 自己组装手摇磨豆机(最灵活,也最折腾)

1. 三种主流安装方式 · 怎么选

方式适合谁优点缺点
🐳 Docker学习、本地、容器化部署干净、版本可控、不污染系统需要先学 Docker 基础
📦 apt / yum服务器运维、已熟悉 Linux一行命令搞定,开机自启版本可能落后半年
🔧 源码编译想加第三方模块(如 OpenResty)高度可定制步骤多、依赖一堆

新手建议:先用 Docker 跑通,理解配置,再考虑别的。下面三种都讲。


2. 方式一 · Docker(推荐 ⭐⭐⭐⭐⭐)

2.1 一行命令把 Nginx 跑起来

bash
docker run -d \
  --name nginx-learn \
  -p 8080:80 \
  nginx:1.25-alpine

参数解释:

参数作用
-d后台运行(detach)
--name给容器起个名(方便后续 stop / rm)
-p 8080:80把宿主机 8080 映射到容器内 80 端口
nginx:1.25-alpine镜像 + 标签(alpine = 极简 Linux,5MB)

打开浏览器访问 http://localhost:8080 → 看到 "Welcome to nginx!" = 成功 ✅

2.2 看看默认配置是啥样

bash
docker exec -it nginx-learn cat /etc/nginx/nginx.conf
bash
docker exec -it nginx-learn ls /etc/nginx/conf.d/

会看到一个 default.conf,里面就是开箱即用的"欢迎页"配置。

2.3 用自己的配置覆盖默认

新建一个目录:

bash
mkdir -p ~/nginx-learn/{html,conf}
echo "<h1>Hello Nginx 👋</h1>" > ~/nginx-learn/html/index.html

写一份最小 conf:

nginx
# ~/nginx-learn/conf/default.conf
server {
    listen 80;
    server_name localhost;

    location / {
        root /usr/share/nginx/html;
        index index.html;
    }
}

启动:

bash
docker run -d --name my-nginx \
  -p 8080:80 \
  -v ~/nginx-learn/html:/usr/share/nginx/html:ro \
  -v ~/nginx-learn/conf/default.conf:/etc/nginx/conf.d/default.conf:ro \
  nginx:1.25-alpine

:ro = 只读挂载,更安全。

2.4 改了配置怎么生效

bash
# 方法 1:reload(推荐,不断连)
docker exec my-nginx nginx -s reload

# 方法 2:重启容器(会断 1 秒连接)
docker restart my-nginx

2.5 关掉 / 删掉

bash
docker stop my-nginx     # 停止
docker rm   my-nginx     # 删除容器
docker rmi  nginx:1.25-alpine   # 删除镜像(一般不需要)

3. 方式二 · apt / yum

3.1 Ubuntu / Debian(apt)

bash
sudo apt update
sudo apt install -y nginx
sudo systemctl enable --now nginx     # 开机自启 + 立即启动

3.2 CentOS / RHEL / 阿里云 Linux(yum / dnf)

bash
sudo yum install -y epel-release
sudo yum install -y nginx
sudo systemctl enable --now nginx

3.3 装完之后的关键路径

路径是啥
/etc/nginx/nginx.conf主配置文件
/etc/nginx/conf.d/*.conf一般虚拟主机配置(按文件拆分)
/etc/nginx/sites-available/Debian 系特有:可用站点配置池
/etc/nginx/sites-enabled/Debian 系特有:实际启用的软链
/var/log/nginx/access.log访问日志
/var/log/nginx/error.log错误日志
/var/www/html/默认网站根目录
/usr/sbin/nginx二进制可执行文件

不同发行版略有差异,记住"主配置在 /etc/nginx/nginx.conf、日志在 /var/log/nginx/"就够 80% 场景。


4. 方式三 · 源码编译(进阶)

bash
# 1. 装编译依赖
sudo apt install -y build-essential libpcre3-dev libssl-dev zlib1g-dev

# 2. 下载源码
wget https://nginx.org/download/nginx-1.25.3.tar.gz
tar zxvf nginx-1.25.3.tar.gz && cd nginx-1.25.3

# 3. 配置(这里加了 SSL、HTTP/2、gzip)
./configure \
  --prefix=/usr/local/nginx \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_gzip_static_module \
  --with-http_stub_status_module

# 4. 编译 + 安装
make && sudo make install

# 5. 启动
/usr/local/nginx/sbin/nginx

什么时候要源码编译?想加官方没集成的模块(比如 nginx-rtmp-modulenginx-upload-module)。日常开发不需要


5. nginx 命令行 5 大动作(记牢)

bash
nginx                # 启动
nginx -s stop        # 立刻停(粗暴)
nginx -s quit        # 优雅停(处理完当前请求再退)
nginx -s reload      # 重载配置 ✨ 90% 用这个
nginx -t             # 仅测试配置文件语法 ⭐ 改配置后必跑

最常见工作流

bash
# 改完 nginx.conf 之后
sudo nginx -t              # ① 先测试语法
sudo nginx -s reload       # ② 没问题就 reload

💡 -t 是救命稻草。直接 reload 配置错了 = nginx 起不来 = 网站 502。养成"reload 前必 -t"的肌肉记忆。


6. 第一次跑通的小作业 ✏️

学会这一章的 4 个动作,下一章才能继续。

任务

  1. 启动一个 Nginx 容器(或装好 Nginx 服务),监听本地 8080 端口
  2. <h1>我的第一个 Nginx 页面 - {你的名字}</h1> 放到默认 root 下
  3. curl http://localhost:8080 看到自己的内容
  4. 停掉 Nginx,再启动它

验收脚本(在 Linux/Mac 上)

bash
# 启动
docker run -d --name first-nginx -p 8080:80 nginx:1.25-alpine

# 把自定义 HTML 拷进去
echo "<h1>我的第一个 Nginx 页面 - LiLei</h1>" | \
  docker exec -i first-nginx tee /usr/share/nginx/html/index.html

# 验证
curl http://localhost:8080
# 期望输出:<h1>我的第一个 Nginx 页面 - LiLei</h1>

# 干掉
docker rm -f first-nginx

跑通了,恭喜你 — Nginx 已经"被你养起来了"。


7. ⚠️ 新手常踩的坑

  1. 80 端口被占bind() to 0.0.0.0:80 failed (98: Address already in use)sudo lsof -i:80 看占用,杀掉对应进程或换端口。
  2. 改了 conf 没生效 → 忘了 nginx -s reload,或者改的是 conf 但 nginx 加载的是另一个 conf → nginx -t 输出里的 the configuration file ... syntax is ok 那一行就是它真正读的文件路径。
  3. Docker 里改宿主机 html 文件没刷出来 → 浏览器缓存。Ctrl+Shift+R 强刷或加查询参数 ?v=1
  4. systemctl status nginx 显示 active 但访问不通 → 防火墙!
    • Ubuntu: sudo ufw allow 80/tcp
    • CentOS: sudo firewall-cmd --add-port=80/tcp --permanent && sudo firewall-cmd --reload
    • 云服务器:还要去安全组里开 80/443
  5. 权限不够 → 直接执行 nginxPermission denied:用 sudo,或者把 worker 改成自己的用户(学习阶段可以)。

8. 章末面试题速览

详见 qa.md 第 4-5 题。

  1. nginx -s reloadrestart 区别? → reload 不断连接、平滑切换;restart 会断开所有连接重启进程。
  2. 改了 conf 没 reload 会咋样? → 不会生效。Nginx 进程还在用旧配置。
  3. 如何让 Nginx 开机自启?systemctl enable nginx(systemd 的标准动作)。

9. 一句话总结

学习用 Docker 一行命令,生产用 apt 加 systemd——记牢 nginx -tnginx -s reload,你就拿到了 Nginx 的"启动按钮"。

下一章 → 03 · 配置文件结构:把配置文件这只洋葱一层层剥开。

💻 示例代码

下方提供了 docker-compose.yml、最小 nginx.conf、和一个完整的 commands.sh 脚本,跟着运行就能起一个本地 Nginx。

💻 示例代码

bash
#!/usr/bin/env bash
# Nginx · 第 02 章 · 一键体验脚本
# 用法:bash commands.sh up      启动
#       bash commands.sh down    停止
#       bash commands.sh logs    跟踪日志
#       bash commands.sh test    nginx -t 测试配置语法
#       bash commands.sh reload  reload 配置(不断连)

set -euo pipefail

CONTAINER=nginx-learn
IMAGE=nginx:1.25-alpine
PORT=${PORT:-8080}
ROOT=$(cd "$(dirname "$0")" && pwd)

cmd_up() {
  mkdir -p "$ROOT/html" "$ROOT/conf" "$ROOT/logs"
  if [ ! -f "$ROOT/html/index.html" ]; then
    cat > "$ROOT/html/index.html" <<'EOF'
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="utf-8"><title>Hello Nginx</title></head>
<body style="font-family:sans-serif;text-align:center;padding:40px;">
  <h1>👋 Hello Nginx</h1>
  <p>第一份属于你的网页 · 来自 Nginx 学习笔记</p>
</body>
</html>
EOF
  fi
  if [ ! -f "$ROOT/conf/default.conf" ]; then
    cp "$ROOT/default.conf" "$ROOT/conf/default.conf"
  fi

  docker rm -f "$CONTAINER" >/dev/null 2>&1 || true
  docker run -d \
    --name "$CONTAINER" \
    -p "${PORT}:80" \
    -v "$ROOT/html:/usr/share/nginx/html:ro" \
    -v "$ROOT/conf/default.conf:/etc/nginx/conf.d/default.conf:ro" \
    -v "$ROOT/logs:/var/log/nginx" \
    "$IMAGE" >/dev/null

  echo "✅ Nginx 已启动 → http://localhost:${PORT}"
  echo "    健康检查 → http://localhost:${PORT}/healthz"
}

cmd_down() {
  docker rm -f "$CONTAINER" >/dev/null 2>&1 || true
  echo "🛑 已停止并移除容器 $CONTAINER"
}

cmd_logs()   { docker logs -f "$CONTAINER"; }
cmd_test()   { docker exec "$CONTAINER" nginx -t; }
cmd_reload() { docker exec "$CONTAINER" nginx -s reload && echo "🔁 Reload 完成"; }
cmd_shell()  { docker exec -it "$CONTAINER" sh; }

case "${1:-}" in
  up)     cmd_up ;;
  down)   cmd_down ;;
  logs)   cmd_logs ;;
  test)   cmd_test ;;
  reload) cmd_reload ;;
  shell)  cmd_shell ;;
  *)
    echo "Usage: $0 {up|down|logs|test|reload|shell}" ;;
esac
txt
server {
    listen       80;
    server_name  localhost;

    access_log  /var/log/nginx/access.log  main;
    error_log   /var/log/nginx/error.log   warn;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    location = /healthz {
        access_log off;
        return 200 "ok\n";
        add_header Content-Type text/plain;
    }

    error_page  500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
yaml
version: "3.8"

services:
  nginx:
    image: nginx:1.25-alpine
    container_name: nginx-learn
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - ./html:/usr/share/nginx/html:ro
      - ./conf/default.conf:/etc/nginx/conf.d/default.conf:ro
      - ./logs:/var/log/nginx
    healthcheck:
      test: ["CMD", "wget", "-q", "-O", "-", "http://localhost/"]
      interval: 30s
      timeout: 5s
      retries: 3

commands.sh ↗ · default.conf ↗ · docker-compose.yml ↗