1. 概述
在容器化部署中,如何安全、穩定地「拉取私有映像檔」是常見需求,本文精簡說明兩件事:
- Docker 在本機或 VM 上如何從 GitLab Registry 拉取 image
- Kubernetes 叢集內如何透過 ImagePullSecret 拉取同一個 image
TL;DR
- Docker:先用 Deploy Token
docker login,再docker pull- Kubernetes:建立
docker-registry類型的 Secret,於imagePullSecrets引用
2. 過去 Docker 怎麼拉取 GitLab Image
2.1 取得 GitLab Deploy Token
進到專案 → Settings → Repository → Deploy tokens
勾選你需要的權限:
- read_registry → 拉 image
- write_registry → 推 image
P.S. 如果你有 Group 權限,也可以申請一個 Group Access Token,這樣就能跨專案拉取images
記下 GitLab 給的 username / password。
2.2 Docker 認證與拉取(本機/VM)
# 清除舊認證(可選)
docker logout registry.abc.com
# 使用 Deploy Token 登入(建議用 --password-stdin)
echo "<deploy_token_password>" | docker login registry.abc.com -u <deploy_token_username> --password-stdin
# 拉取測試
docker pull registry.abc.com/kong/kong-api-gateway/main:70368
為什麼建議使用 --password-stdin?
- 避免密碼出現在命令列歷史(例如
~/.bash_history、PowerShell 歷史)。 - 避免密碼暴露在系統程序列表(Linux
ps、WindowsGet-CimInstance Win32_Process會看得到參數)。 - 適合 CI/CD 無互動環境,搭配隱藏的環境變數(masked secrets)更安全。
- 官方不建議用
--password明文參數;使用標準輸入更安全且可審計。
範例(更安全的一次性輸入):
# Bash / Linux / macOS:建議用 printf 避免 echo 行為差異
printf "%s" "$DEPLOY_TOKEN" | docker login registry.abc.com -u "$DEPLOY_USER" --password-stdin
# Windows PowerShell
$Env:DEPLOY_TOKEN | docker login registry.abc.com -u $Env:DEPLOY_USER --password-stdin
2.3 若 Registry 無 HTTPS(Insecure Registry)
若你的 Registry 沒有 HTTPS,需在 Docker Daemon 設定 insecure-registries:
# 編輯 Docker daemon 配置
sudo nano /etc/docker/daemon.json
# 加入以下內容
{
"insecure-registries": ["registry.abc.com:5000", "192.168.1.100:5000"]
}
# 重啟 Docker 服務
sudo systemctl restart docker
# 或者重啟 Docker Desktop (Windows/Mac)
注意事項:
- 生產環境不建議使用 HTTP registry
- 如果是自建的 GitLab registry,建議配置 SSL 證書
- 開發環境可以使用 HTTP,但要注意安全性
3. K8s 怎麼拉取
3.1 建立 ImagePullSecret
在要部署的命名空間建立一個 docker-registry 類型的 Secret:
# 建立 Docker Registry Secret
kubectl create secret docker-registry kong-api-gateway-secret \
--docker-server=registry.abc.com \
--docker-username=<deploy_token_username> \
--docker-password=<deploy_token_password> \
--docker-email=none \
-n <your-namespace>
3.2 在 Deployment 引用
apiVersion: apps/v1
kind: Deployment
metadata:
name: kong-api-gateway
spec:
replicas: 1
selector:
matchLabels:
app: kong-api-gateway
template:
metadata:
labels:
app: kong-api-gateway
spec:
containers:
- name: kong
image: registry.abc.com/kong/kong-api-gateway/main:70368
ports:
- containerPort: 8000
imagePullSecrets:
- name: kong-api-gateway-secret
3.3 驗證功能
# 檢查 Secret 是否建立成功(命名空間必須正確)
kubectl get secret kong-api-gateway-secret -n <your-namespace> -o yaml
# 重新建立 Secret
kubectl delete secret kong-api-gateway-secret -n <your-namespace>
kubectl create secret docker-registry kong-api-gateway-secret \
--docker-server=registry.abc.com \
--docker-username=<deploy_token_username> \
--docker-password=<deploy_token_password> \
--docker-email=none \
-n <your-namespace>
補充
- Secret 是「命名空間範圍」,必須與工作負載在同一個命名空間。
- 想讓該命名空間所有 Pod 都能自動拉私有 image,可把 Secret 加到該命名空間的預設 ServiceAccount。
- Secret 不可跨命名空間共用;需要時請在目標命名空間各自建立或同步。
# 檢查 Secret 是否存在於指定命名空間
kubectl get secret kong-api-gateway-secret -n <your-namespace>
# 將 Secret 掛到該命名空間的 default ServiceAccount
kubectl patch serviceaccount default -n <your-namespace> -p '{"imagePullSecrets":[{"name":"kong-api-gateway-secret"}]}'
可以幫你把這段再精簡成更好懂的「安全金鑰使用說明」,保留重點但去掉技術贅字:
4. 補充:GitLab 金鑰安全
在 GitLab 使用金鑰或密碼時,要注意以下幾點,避免外洩:
4.1 Masked 變數
- 功能:啟用後,變數值在 CI 日誌裡會變成
[MASKED],不會顯示真實內容。 - 限制:必須符合 GitLab 規則(至少 8 字元、英數字+部分符號),不支援空白或換行。
- 建議:如果有換行或特殊字元,改用 File 變數 或先 Base64 編碼。
- 更安全:同時設成 Protected,只允許在受保護分支/標籤使用。
4.2 File 類型變數(推薦存放多行金鑰)
適合 SSH 私鑰、Kubeconfig、JSON 憑證等。
- 在 GitLab 設定變數時,類型選 File,直接貼上完整內容(含換行)。
- 在 Pipeline 裡,變數變成 檔案路徑,而不是字串。
範例:
chmod 600 "$SSH_PRIVATE_KEY"
GIT_SSH_COMMAND="ssh -i $SSH_PRIVATE_KEY -o StrictHostKeyChecking=no" \
git ls-remote [email protected]:group/project.git
4.3 避免密鑰被印出
- 用 標準輸入傳遞密碼,避免出現在命令列或 shell 歷史。
- 在有密鑰的地方關掉
set -x。
範例:
printf "%s" "$DEPLOY_TOKEN" | docker login registry.abc.com -u "$DEPLOY_USER" --password-stdin
4.4 權限最小化
- 只給需要的權限(例如 Deploy Token 用
read_registry就好)。 - 設定變數的使用範圍(特定分支/環境)。
- Token 要有 到期日,並定期更新。
4.5 密碼安全技巧
--password-stdin:避免密碼出現在命令列。- File/Masked/Protected 變數:避免 CI 日誌洩漏。
- K8s ImagePullSecret:避免憑證寫死在 YAML。
- 額外建議:用完就
unset,刪除暫存檔,Runner 啟用清理,K8s 啟用 Secret 加密。
4.6 常見錯誤(不要這樣做)
- 把密碼寫在
docker login -p、Dockerfile、YAML、.env 檔裡。 - 在 MR/Issue/聊天中貼出完整的錯誤訊息或日誌,裡面包含密鑰。
- 在不同命名空間重複用同一個 Secret。





















留言