本文章會介紹 Nginx 的基本概念以及如何在 Mac 上安裝 Nginx,適合第一次接觸 Nginx 的讀者閱讀,將會了解到

  • 如何在 Mac 安裝 Nginx
  • Nginx 的基本概念
  • 如何設定 virtual host (多個 domain name 對到同一個 IP)

本文章主要是參考資料翻譯及整理而來,如果是喜歡閱讀英文或是更完整資訊的朋友,可以依照參考資料的順序閱讀

Nginx 安裝

安裝 Homebrew

Homebrew 是 Mac 上的套件管理工具,以下的軟體都會透過 Homebrew 來安裝

1
2
xcode-select --install
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

將 Homebrew 安裝 tool 的路徑加入環境變數

1
2
3
4
5
6
7
8
9
10
11
##
# ~/.bash_profile
##
export PATH="/usr/local/bin:$PATH"
export PATH="/usr/local/sbin:$PATH"
##
# ~/.zshrc
##
export PATH="/usr/local/bin:$PATH"
export PATH="/usr/local/sbin:$PATH"

安裝 Nginx

透過 Homebrew 安裝 Nginx

1
brew install nginx

預設開機啟動 Nginx,將 plist 檔複製至 Launch Daemon/Agent

1
2
3
4
5
# 開機後,以一般使用者身份啟動 Nginx
cp /usr/local/opt/nginx/homebrew.mxcl.nginx.plist ~/Library/LaunchAgents/
# 開機後,要以 root 身份啟動 Nginx
sudo cp /usr/local/opt/nginx/homebrew.mxcl.nginx.plist /Library/LaunchDaemons/

啟動 Nginx

1
2
3
4
5
# 啟動 Nginx
nginx
# 如果設定檔牽涉 root 權限,就要以 root 啟動 nginx
sudo nginx

一旦 Nginx 啟動後,可以透過 -s 參數對 nginx 下指令

1
nginx -s signal

signal 必須是以下幾種

訊號 意義
stop 直接停止 Nginx
quit 等目前正在服務的 worker process 結束後,停止 Nginx
reload 重新載入設定檔,Nginx 依照新的設定產生新的 worker process,既有的 woker process 會在服務完既有的連線後停止,在重啟前可以用 nginx -t 檢驗語法是否正確
reopen 重新開啟 log 檔案

Nginx 基本概念

Nginx 是由一個主線程 (main process) 及多個工作線程 (worker processes),主線成主要的功能是讀取及執行設定檔、維護工作線程,工作線程則是處理請求 (request),Nginx 是事件驅動 (event-based) 和 OS-dependent,藉此達到有效的處理請求

設定檔結構

Nginx 組成的模組是由設定檔內的 directives 所控制,directives 可以分成 simple directives、block directives

  • simple directives : 由名稱及參數組合而成,中間由空白鍵分割,分號結尾
  • block directives : 由大括號{}表示起始跟結尾,中間可以包含其他 directives,被包含的 directives 被稱為內容 (context)

設定檔中不屬於任何 block directives 的 directives 稱為 main context,eventhttp 是 main context,server 包含在 httplocation 包含在 server

1
2
3
4
5
6
7
8
9
10
11
12
worker_processes 1; # main context, simple directive
http { # block context
access_log /var/logs/access.log; # context, simple directive
server {
location {
...
}
...
}
...
}

靜態檔案

Nginx 可以根據 location block 將請求分別導向不同資料夾下的檔案,範例中的 location / { ... }/ 會去比對請求的 URI,若比對符合就會將 URI 加在 root 所定義的路徑後,回傳請求的檔案,而 location /images/ {...} 則會去比對 /images/ 開頭的 URI,比對符合後,一樣會將 URI 加在 root 所定義的路徑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# /usr/local/etc/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
access_log /usr/local/etc/nginx/logs/access.log;
error_log /usr/local/etc/nginx/logs/error.log;
server {
listen 80;
server_name localhost;
location / {
root /data/www;
}
location /images/ {
root /data;
}
}
}

上述設定黨範例:

設定檔更新後,要重新載入設定檔

1
sudo nginx -s reload

範例中的 http://localhost/images/sample.jpg 同時符合 location / {...}location /images/ {...},當請求的 URI 符合兩個以上的 location directive 時,會優先選取比對條件較長的 (/images// 長),所以一般會將越長的比對條件寫在下面,以方便閱讀,如果都找不到符合的檔案時,Nginx 會回傳 404

:::info
當 Nginx 的行為不符合預期時,可以多檢視access_logerror_log定義的 log 檔案
:::

如何設定 virtual host

virtual host 是將多個 domain name 指向同一個 IP (即同一台伺服器),Nginx 會依據server blockportserver_name決定該server block處理那個種類 (domain name) 的請求

建立各專案的根目錄

1
2
mkdir -p /your/project/name1/html
mkdir -p /your/project/name2/html

:::info
如果是在 Linux 系統下,可能會要使用chown,chmod對檔案做權限設定,允許www-data使用者具有rwx的權限
:::

建立範例檔案

1
2
3
4
5
6
7
8
# /your/project/name1/html/index.html
<html>
<head>
</head>
<body>
<h1>Welcome name1 !</h1>
</body>
</html>
1
2
3
4
5
6
7
8
# /your/project/name2/html/index.html
<html>
<head>
</head>
<body>
<h1>Welcome name2 !</h1>
</body>
</html>

對每個 domain 建立 server block

將每個 server block 設定檔儲存在 /usr/local/etc/nginx/serversnginx.conf 預設會將 servers 資料夾下的檔案載入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# /usr/local/etc/nginx/servers/project_name1
server {
# 監聽的 port
listen 80;
listen [::]:80;
# 起始資料夾位置
root /your/project/name1/html;
# 當找不到符合的檔案後,會加入 index.html,再比對一次
index index.html;
# client 端輸入的 domain name
server_name project_name1.com;
location / {
# 驗證檔案 $uri、資料夾 $uri/ 是否存在,都不存在則回傳 404
try_files $uri $uri/ =404;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# /usr/local/etc/nginx/servers/project_name2
server {
listen 80;
listen [::]:80;
root /your/project/name2/html;
index index.html;
server_name project_name2.com;
location / {
try_files $uri $uri/ =404;
}
}

:::info
Mac 的 *.conf 設定檔慣例上是放在 servers 資料夾下,如果是 Ubuntu 會建立 sites-available 及 sites-enable 兩個資料夾,將設定檔放在 sites-available 資料夾下,然後將要載入的設定檔以連結 (ln -s) 的方式連結至 sites-enable 資料夾
:::

設定本機端的 DNS

1
2
3
# /etc/hosts
127.0.0.1 project_name1.com
127.0.0.1 project_name2.com

設定完成後,重啟 Nginx,在網頁上輸入 http://project_name1.com 即可看到建立好的範例頁了

:::info
這邊先將測試的 Domain Name 導向 127.0.0.1,實際情況會由 DNS 導向實際對外開放的 Nginx server
:::

參考資料