在現代 Web 架構中,NGINX 已成為不可或缺的元件,尤其在容器化環境下,其靈活性更能滿足動態擴充套件的需求。本文將引導讀者瞭解如何結合 DNS SRV 記錄與 NGINX Plus,實作自動化服務發現和負載平衡,同時也提供使用官方 NGINX 容器映像和自定義 Dockerfile 的實務技巧,讓佈署流程更加流暢。此外,文章也涵蓋了 NGINX Plus 容器映像檔的建置方法,並探討如何在 NGINX 組態中使用環境變數,以及在 Kubernetes 上佈署 NGINX Ingress Controller 的步驟,提供讀者全方位的 NGINX 容器化解決方案。
NGINX 容器化與 DNS SRV 記錄整合應用
NGINX 在現代化的雲端基礎設施和容器化環境中扮演著至關重要的角色。隨著動態基礎設施的日益普及,NGINX 的靈活性和強大的功能使其成為實作高效負載平衡和 API Gateway 的理想選擇。
使用 DNS SRV 記錄與 NGINX Plus
在動態基礎設施環境中,自動擴充套件(Auto Scaling)功能允許根據負載需求動態增加或減少伺服器數量。為了使負載平衡器能夠動態地新增或移除資源,需要利用 DNS SRV 記錄。NGINX Plus 提供了對 DNS SRV 記錄的支援,使得管理容器化環境中的服務變得更加容易。
設定範例
http {
resolver 10.0.0.2 valid=30s;
upstream backend {
zone backends 64k;
server api.example.internal service=http resolve;
}
}
內容解密:
resolver 10.0.0.2 valid=30s;:指定 DNS 解析器為10.0.0.2,並設定 DNS 解析結果的有效期為 30 秒。upstream backend { ... }:定義了一個名為backend的 upstream 區塊,用於負載平衡。zone backends 64k;:為 upstream 區塊設定分享記憶體區域,用於儲存負載平衡的狀態。server api.example.internal service=http resolve;:指定使用api.example.internal的 SRV 記錄進行負載平衡,並啟用動態解析。
使用官方 NGINX 容器映像
NGINX 提供了官方的容器映像,可以輕鬆地在 Docker 環境中使用。預設情況下,該映像包含了一個基本的 NGINX 組態。
範例指令
$ docker run --name my-nginx -p 80:80 \
-v /path/to/content:/usr/share/nginx/html:ro -d nginx
內容解密:
docker run --name my-nginx -p 80:80: 使用 Docker 執行一個名為my-nginx的容器,並將本地的 80 連線埠對映到容器的 80 連線埠。-v /path/to/content:/usr/share/nginx/html:ro: 將本地的/path/to/content目錄掛載到容器的/usr/share/nginx/html目錄,並以唯讀模式掛載。-d nginx: 以背景模式執行 NGINX 容器。
建立 NGINX Dockerfile
若需要自定義 NGINX 容器映像,可以建立一個 Dockerfile。
範例 Dockerfile 片段
FROM debian:12
# 更新套件管理器並安裝必要的套件
RUN apt-get update && apt-get install -y curl gnupg2 ca-certificates lsb-release
# 新增 NGINX 的官方儲存函式庫和簽名金鑰
RUN curl -s https://nginx.org/keys/nginx_signing.key | apt-key add -
RUN echo "deb https://nginx.org/packages/debian `lsb_release -cs` nginx" | tee /etc/apt/sources.list.d/nginx.list
# 安裝 NGINX
RUN apt-get update && apt-get install -y nginx
# 複製自定義的 NGINX 組態檔案
COPY nginx.conf /etc/nginx/nginx.conf
# EXPOSE 連線埠
EXPOSE 80
內容解密:
FROM debian:12:使用 Debian 12 作為基礎映像。RUN apt-get update && apt-get install -y ...:更新套件列表並安裝必要的套件。COPY nginx.conf /etc/nginx/nginx.conf:將自定義的nginx.conf檔案複製到容器中的/etc/nginx/nginx.conf。EXPOSE 80:宣告容器將使用 80 連線埠。
建置 NGINX 容器映像檔
在容器化環境中使用 NGINX 時,建置自訂的容器映像檔能夠提供更大的彈性與控制力。本章節將探討如何建立 NGINX 與 NGINX Plus 的容器映像檔。
使用官方 NGINX 映像檔
NGINX 官方提供了預建的 Docker 映像檔,可以直接使用。這些映像檔包含了 NGINX 的核心功能,並且經過了官方的測試與驗證。要使用官方映像檔,您只需從 Docker Hub 提取即可:
docker pull nginx:latest
內容解密:
docker pull nginx:latest:從 Docker Hub 提取最新版本的 NGINX 官方映像檔。- 使用官方映像檔的好處是快速佈署和簡單易用,但可能無法滿足特定的自訂需求。
建立自訂 NGINX 映像檔
有時,您需要根據特定的需求來自訂 NGINX 映像檔。這可以透過建立自己的 Dockerfile 來實作。以下是一個範例 Dockerfile,用於建置包含 NGINX 的 Debian 基礎映像檔:
FROM debian:bookworm-slim
LABEL maintainer="Your Name <your.email@example.com>"
ENV NGINX_VERSION 1.25.3
ENV NJS_VERSION 0.8.2
ENV PKG_RELEASE 1~bookworm
RUN set -x \
&& groupadd --system --gid 101 nginx \
&& useradd --system --gid nginx --no-create-home --home /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y gnupg1 ca-certificates \
&& NGINX_GPGKEY=573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62; \
NGINX_GPGKEY_PATH=/usr/share/keyrings/nginx-archive-keyring.gpg; \
export GNUPGHOME="$(mktemp -d)"; \
found=''; \
for server in hkp://keyserver.ubuntu.com:80 pgp.mit.edu; do \
echo "Fetching GPG key $NGINX_GPGKEY from $server"; \
gpg1 --keyserver "$server" --keyserver-options timeout=10 --recv-keys "$NGINX_GPGKEY" && found=yes && break; \
done; \
test -z "$found" && echo >&2 "error: failed to fetch GPG key $NGINX_GPGKEY" && exit 1; \
gpg1 --export "$NGINX_GPGKEY" > "$NGINX_GPGKEY_PATH"; \
rm -rf "$GNUPGHOME"; \
apt-get remove --purge --auto-remove -y gnupg1 && rm -rf /var/lib/apt/lists/* \
&& dpkgArch="$(dpkg --print-architecture)" \
&& nginxPackages="nginx=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-xslt=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-geoip=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-image-filter=${NGINX_VERSION}-${PKG_RELEASE} nginx-module-njs=${NGINX_VERSION}+${NJS_VERSION}-${PKG_RELEASE}" \
&& case "$dpkgArch" in \
amd64|arm64) \
echo "deb [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \
&& apt-get update \
;; \
*) \
echo "deb-src [signed-by=$NGINX_GPGKEY_PATH] https://nginx.org/packages/mainline/debian/ bookworm nginx" >> /etc/apt/sources.list.d/nginx.list \
&& tempDir="$(mktemp -d)" \
&& chmod 777 "$tempDir" \
&& savedAptMark="$(apt-mark showmanual)" \
&& apt-get update \
&& apt-get build-dep -y $nginxPackages \
&& (cd "$tempDir" && DEB_BUILD_OPTIONS="nocheck parallel=$(nproc)" apt-get source --compile $nginxPackages) \
&& apt-mark showmanual | xargs apt-mark auto > /dev/null \
&& { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \
&& ls -lAFh "$tempDir" \
&& (cd "$tempDir" && dpkg-scanpackages . > Packages) \
&& grep '^Package: ' "$tempDir/Packages" \
&& echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list \
&& apt-get -o Acquire::GzipIndexes=false update \
;; \
esac \
&& apt-get install --no-install-recommends --no-install-suggests -y $nginxPackages gettext-base curl \
&& apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \
&& if [ -n "$tempDir" ]; then apt-get purge -y --auto-remove && rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; fi \
&& ln -sf /dev/stdout /var/log/nginx/access.log \
&& ln -sf /dev/stderr /var/log/nginx/error.log \
&& mkdir /docker-entrypoint.d
COPY docker-entrypoint.sh /
COPY 10-listen-on-ipv6-by-default.sh /docker-entrypoint.d
COPY 15-local-resolvers.envsh /docker-entrypoint.d
COPY 20-envsubst-on-templates.sh /docker-entrypoint.d
COPY 30-tune-worker-processes.sh /docker-entrypoint.d
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]
內容解密:
FROM debian:bookworm-slim:使用 Debian slim 版本作為基礎映像檔,以減少映像檔大小。ENV NGINX_VERSION 1.25.3:設定 NGINX 版本環境變數。RUN set -x:啟動詳細模式,便於除錯。- 建立
nginx使用者與群組,以符合 Docker 最佳實踐。 - 使用 GPG 金鑰驗證 NGINX 套件的真實性。
- 根據架構(amd64 或 arm64)安裝 NGINX 或建置 NGINX 套件。
- 設定 NGINX 日誌輸出到
/dev/stdout和/dev/stderr,以便 Docker 日誌收集。 - 複製相關指令碼到映像檔中,用於容器啟動時的設定與調整。
ENTRYPOINT ["/docker-entrypoint.sh"]:指定容器啟動時的入口點指令碼。CMD ["nginx", "-g", "daemon off;"]:預設啟動 NGINX,並在前台執行。
建置 NGINX Plus 容器映像檔
對於 NGINX Plus 使用者,可以參考 F5 官方維護的部落格文章,裡面提供了建置 NGINX Plus 容器映像檔的 Dockerfile 範例。這些範例會根據最新的 NGINX Plus 版本進行更新。
此圖示說明瞭建置流程:
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title NGINX 容器化整合 DNS SRV 記錄應用
package "Docker 架構" {
actor "開發者" as dev
package "Docker Engine" {
component [Docker Daemon] as daemon
component [Docker CLI] as cli
component [REST API] as api
}
package "容器運行時" {
component [containerd] as containerd
component [runc] as runc
}
package "儲存" {
database [Images] as images
database [Volumes] as volumes
database [Networks] as networks
}
cloud "Registry" as registry
}
dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置
@enduml此圖示呈現了從選擇基礎映像檔到佈署容器的整個建置流程。
在Docker中建置NGINX Plus容器映像檔
本章節將指導您如何使用Dockerfile建置NGINX Plus容器映像檔,並探討在不同環境中使用環境變數的技巧,以及在Kubernetes上佈署NGINX Ingress Controller的方法。
使用Dockerfile建置NGINX Plus容器映像檔
要建置NGINX Plus容器映像檔,首先需要下載NGINX Plus儲存函式庫憑證(nginx-repo.crt和nginx-repo.key),並將它們存放在包含Dockerfile的目錄中。Dockerfile會處理剩下的安裝工作。
Dockerfile範例
# 使用官方基礎映像檔
FROM ubuntu:latest
# 複製NGINX Plus憑證到容器中
COPY nginx-repo.crt /etc/ssl/nginx/nginx-repo.crt
COPY nginx-repo.key /etc/ssl/nginx/nginx-repo.key
# 安裝NGINX Plus
RUN apt-get update && \
apt-get install -y ca-certificates && \
# 安裝NGINX Plus的步驟...
# 複製NGINX設定檔到容器中
COPY nginx.conf /etc/nginx/nginx.conf
# 暴露NGINX服務的連線埠
EXPOSE 80 443
# 啟動NGINX服務
CMD ["nginx", "-g", "daemon off;"]
建置Docker映像檔
使用以下命令建置Docker映像檔,並確保每次建置時都從NGINX Plus儲存函式庫提取最新的套件:
$ docker build --no-cache -t nginx-plus .
#### 內容解密:
FROM ubuntu:latest:使用最新的Ubuntu作為基礎映像檔。COPY nginx-repo.crt /etc/ssl/nginx/nginx-repo.crt和COPY nginx-repo.key /etc/ssl/nginx/nginx-repo.key:將NGINX Plus的憑證複製到容器中的指定路徑。RUN apt-get update && apt-get install -y ca-certificates:更新套件列表並安裝CA憑證,這是安裝NGINX Plus的前提條件。COPY nginx.conf /etc/nginx/nginx.conf:將自訂的NGINX設定檔複製到容器中,取代預設設定。EXPOSE 80 443:暴露HTTP和HTTPS服務的連線埠。CMD ["nginx", "-g", "daemon off;"]:設定容器啟動時執行的命令,啟動NGINX服務。
在NGINX組態中使用環境變數
要在NGINX組態中使用環境變數,需要使用支援Perl模組的NGINX容器映像檔,例如nginx:stable-perl。透過perl_set指令,可以將環境變數暴露給NGINX組態。
NGINX組態範例
load_module /modules/ngx_http_perl_module.so;
env APP_DNS;
http {
perl_set $upstream_app 'sub { return $ENV{"APP_DNS"}; }';
server {
location / {
proxy_pass https://$upstream_app;
}
}
}
#### 內容解密:
load_module /modules/ngx_http_perl_module.so;:載入NGINX的Perl模組。env APP_DNS;:保留環境變數APP_DNS。perl_set $upstream_app 'sub { return $ENV{"APP_DNS"}; }';:使用Perl模組設定變數$upstream_app,使其值等於環境變數APP_DNS的值。proxy_pass https://$upstream_app;:將請求代理到由$upstream_app指定的網域。
在Kubernetes上佈署NGINX Ingress Controller
要在Kubernetes上佈署應用,需要使用Ingress Controller。您可以選擇使用NGINX Open Source或NGINX Plus的Ingress Controller映像檔。
佈署步驟
- 建立Namespace和Service Account:
$ kubectl apply -f common/ns-and-sa.yaml - 可選:建立ConfigMap以自訂NGINX組態:
$ kubectl apply -f common/nginx-config.yaml - 如果叢集啟用了RBAC,建立Cluster Role並繫結到Service Account:
$ kubectl apply -f rbac/rbac.yaml - 佈署Ingress Controller(Deployment或DaemonSet):
- NGINX Deployment:
$ kubectl apply -f deployment/nginx-ingress.yaml - NGINX Plus Deployment(需修改YAML檔案以指定自己的registry和image):
$ kubectl apply -f deployment/nginx-plus-ingress.yaml
- NGINX Deployment:
#### 內容解密:
- 建立Namespace和Service Account:為Ingress Controller建立獨立的Namespace和Service Account,有助於資源管理和許可權控制。
- 建立ConfigMap:透過ConfigMap,可以在不修改Ingress Controller映像檔的情況下,自訂NGINX組態。
- 佈署Ingress Controller:根據叢集需求,選擇Deployment或DaemonSet來佈署Ingress Controller。