Mark Ku's Blog
首頁 關於我
Docker 及 K8s 如何拉取映像檔
DevOps
Docker 及 K8s 如何拉取映像檔
Mark Ku
Mark Ku
September 02, 2025
1 min

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、Windows Get-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 憑證等。

  1. 在 GitLab 設定變數時,類型選 File,直接貼上完整內容(含換行)。
  2. 在 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。

Tags

Mark Ku

Mark Ku

Software Developer

10年以上豐富網站開發經驗,開發過各種網站,電子商務、平台網站、直播系統、POS系統、SEO 優化、金流串接、AI 串接,Infra 出身,帶過幾次團隊,也加入過大團隊一起開發。

Expertise

前端(React)
後端(C#)
網路管理
DevOps
溝通
領導

Social Media

facebook github website

Related Posts

幾個常見在 K8s 上的映像檔建置方法:Docker(DinD DooD)/Kaniko/BuildKit
幾個常見在 K8s 上的映像檔建置方法:Docker(DinD DooD)/Kaniko/BuildKit
September 01, 2025
1 min

Quick Links

關於我

Social Media