建立: 2026年1月26日 10:15:09
更新: 2026年1月26日 10:15:09
作者: Charles
LAB 05 建置 private registry¶
學習目標¶
完成本章節後,你將能夠:
- 區分 Public Registry 與 Private Registry 的用途
- 熟練操作 Docker 基本指令(run、exec、logs、inspect 等)
- 設定 Docker 持久化儲存(Volumes 與 Bind Mounts)
- 理解並設定 Docker 網路
- 從 Docker Hub 搜尋、拉取、推送 Image
- 完成 WordPress + MySQL 容器化部署實作
前置知識¶
開始之前,請確保你已經:
- 完成第 1 章的內容
- Docker 已正確安裝並可執行
- 理解 Image 與 Container 的關係
2.1 Public Registry 與 Private Registry¶
什麼是 Registry?¶
Registry(倉庫)是用來儲存和分發 Docker Image 的服務。就像 GitHub 儲存程式碼一樣,Registry 儲存容器映像檔。
graph LR
Dev[開發者] -->|push| Registry[(Registry)]
Registry -->|pull| Server1[伺服器 1]
Registry -->|pull| Server2[伺服器 2]
Registry -->|pull| Server3[伺服器 3]
Public Registry¶
公開的 Registry 服務,任何人都可以存取公開的 Image。
| Registry | 說明 | 網址 |
|---|---|---|
| Docker Hub | 官方預設 Registry,最大的公開 Image 倉庫 | hub.docker.com |
| Quay.io | Red Hat 提供的 Registry | quay.io |
| GitHub Container Registry | GitHub 提供的容器 Registry | ghcr.io |
| Google Container Registry | Google Cloud 提供 | gcr.io |
| Amazon ECR Public | AWS 提供的公開 Registry | public.ecr.aws |
Docker Hub 使用技巧
- 官方 Image:沒有前綴,如
nginx、mysql、redis - 社群 Image:包含使用者名稱,如
bitnami/nginx - 標籤:指定版本,如
nginx:1.25、nginx:alpine
Private Registry¶
私有 Registry 用於儲存企業內部的 Image,不對外公開。
常見私有 Registry 方案¶
| 方案 | 說明 | 適用場景 |
|---|---|---|
| Docker Registry | Docker 官方提供的輕量級 Registry | 小型團隊、測試環境 |
| Harbor | VMware 開源的企業級 Registry | 大型企業、需要 RBAC |
| Nexus Repository | Sonatype 的多功能倉庫 | 已使用 Nexus 管理套件 |
| JFrog Artifactory | 企業級製品管理 | 大型企業 |
| AWS ECR | AWS 私有 Registry | AWS 雲端環境 |
| Azure ACR | Azure 私有 Registry | Azure 雲端環境 |
| GCP GCR | Google 私有 Registry | GCP 雲端環境 |
建立簡易 Private Registry¶
使用 Docker 建立私有 Registry
# 啟動 Registry Container
docker run -d \
--name my-registry \
-p 5000:5000 \
-v registry-data:/var/lib/registry \
registry:2
# 為 Image 加上私有 Registry 標籤
docker tag nginx:latest localhost:5000/my-nginx:v1
# 推送到私有 Registry
docker push localhost:5000/my-nginx:v1
# 從私有 Registry 拉取
docker pull localhost:5000/my-nginx:v1
生產環境注意事項
- 私有 Registry 應配置 TLS 憑證
- 設定適當的存取控制
- 定期備份 Registry 資料
- 考慮使用企業級方案如 Harbor
2.2 Docker 基本操作¶
Container 生命週期管理¶
stateDiagram-v2
[*] --> Created: docker create
Created --> Running: docker start
Running --> Paused: docker pause
Paused --> Running: docker unpause
Running --> Stopped: docker stop
Stopped --> Running: docker start
Stopped --> Removed: docker rm
Running --> Removed: docker rm -f
Removed --> [*]
核心指令詳解¶
docker run - 執行容器¶
docker run 常用選項
# 基本執行
docker run nginx
# 背景執行 (detached)
docker run -d nginx
# 指定名稱
docker run -d --name my-nginx nginx
# Port 對應 (主機:容器)
docker run -d -p 8080:80 nginx
# 環境變數
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql
# 自動刪除(結束後自動移除)
docker run --rm nginx echo "Hello"
# 互動模式
docker run -it ubuntu /bin/bash
# 資源限制
docker run -d --memory="512m" --cpus="1.0" nginx
# 重啟策略
docker run -d --restart=always nginx
docker run 選項說明
| 選項 | 說明 |
|---|---|
-d |
Detached mode,背景執行 |
-it |
互動模式 + TTY |
-p |
Port mapping |
-v |
Volume mapping |
-e |
環境變數 |
--name |
指定容器名稱 |
--rm |
結束後自動刪除 |
--restart |
重啟策略 |
docker exec - 執行指令¶
在運行中的容器執行指令
# 執行單一指令
docker exec my-nginx cat /etc/nginx/nginx.conf
# 進入互動式 Shell
docker exec -it my-nginx /bin/bash
# 以特定使用者執行
docker exec -u root my-nginx whoami
# 設定環境變數
docker exec -e VAR=value my-nginx printenv VAR
docker logs - 檢視日誌¶
Container 日誌操作
# 檢視全部日誌
docker logs my-nginx
# 持續追蹤日誌
docker logs -f my-nginx
# 顯示最後 N 行
docker logs --tail 100 my-nginx
# 顯示時間戳記
docker logs -t my-nginx
# 指定時間範圍
docker logs --since 2024-01-01 my-nginx
docker logs --since 10m my-nginx # 最近 10 分鐘
docker inspect - 檢視詳細資訊¶
檢視容器/映像檔詳細資訊
# 檢視容器詳細資訊(JSON 格式)
docker inspect my-nginx
# 取得特定資訊(使用 Go 模板)
docker inspect --format='{{.NetworkSettings.IPAddress}}' my-nginx
# 取得 Port 對應
docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{$p}} -> {{(index $conf 0).HostPort}}{{end}}' my-nginx
# 取得掛載資訊
docker inspect --format='{{json .Mounts}}' my-nginx | jq .
其他常用指令¶
容器管理指令
# 列出運行中的容器
docker ps
# 列出所有容器(包含已停止)
docker ps -a
# 停止容器
docker stop my-nginx
# 啟動已停止的容器
docker start my-nginx
# 重啟容器
docker restart my-nginx
# 刪除容器
docker rm my-nginx
# 強制刪除運行中的容器
docker rm -f my-nginx
# 刪除所有已停止的容器
docker container prune
# 檢視容器資源使用
docker stats
# 複製檔案到容器
docker cp ./index.html my-nginx:/usr/share/nginx/html/
# 從容器複製檔案
docker cp my-nginx:/etc/nginx/nginx.conf ./nginx.conf
2.3 Persistent Storage¶
為什麼需要持久化儲存?¶
Container 預設的資料是短暫的(ephemeral),當 Container 被刪除時,所有資料都會消失。
graph LR
subgraph "沒有持久化"
C1[Container] --> RW1[讀寫層]
RW1 -.->|刪除容器| X[資料消失]
end
subgraph "使用持久化"
C2[Container] --> RW2[讀寫層]
C2 --> V[Volume/Bind Mount]
V -->|容器刪除| V
end
三種儲存方式¶
| 類型 | 說明 | 適用場景 |
|---|---|---|
| Volume | 由 Docker 管理的儲存區域 | 生產環境、資料持久化 |
| Bind Mount | 將主機目錄掛載到容器 | 開發環境、程式碼同步 |
| tmpfs Mount | 儲存在主機記憶體中 | 暫存敏感資料 |
Volumes¶
Volume 基本操作
# 建立 Volume
docker volume create my-data
# 列出所有 Volume
docker volume ls
# 檢視 Volume 詳細資訊
docker volume inspect my-data
# 使用 Volume 執行容器
docker run -d \
--name my-nginx \
-v my-data:/usr/share/nginx/html \
nginx
# 刪除 Volume
docker volume rm my-data
# 清理未使用的 Volume
docker volume prune
Volume 位置
Docker Volume 預設儲存在:
- Linux:
/var/lib/docker/volumes/ - macOS/Windows: Docker Desktop 管理的虛擬磁碟內
Bind Mounts¶
Bind Mount 使用方式
# 使用 -v 語法
docker run -d \
--name my-nginx \
-v /path/on/host:/usr/share/nginx/html \
-p 8080:80 \
nginx
# 使用 --mount 語法(推薦)
docker run -d \
--name my-nginx \
--mount type=bind,source=/path/on/host,target=/usr/share/nginx/html \
-p 8080:80 \
nginx
# 唯讀掛載
docker run -d \
--name my-nginx \
-v /path/on/host:/usr/share/nginx/html:ro \
nginx
開發環境範例
前端開發即時同步
# 將本地專案目錄掛載到容器
docker run -d \
--name frontend-dev \
-v $(pwd)/src:/app/src \
-p 3000:3000 \
node:18
修改本地 src 目錄的檔案會立即反映到容器中。
Volume vs Bind Mount 比較¶
| 比較項目 | Volume | Bind Mount |
|---|---|---|
| 儲存位置 | Docker 管理 | 指定主機路徑 |
| 可移植性 | 高 | 依賴主機路徑 |
| 效能 | 較佳 | 取決於主機檔案系統 |
| 備份 | 容易 | 需手動處理 |
| 適用場景 | 生產環境 | 開發環境 |
2.4 Docker Network¶
預設網路類型¶
Docker 提供多種網路驅動,滿足不同的使用場景。
graph TB
subgraph "Bridge Network(預設)"
B_C1[Container 1] --- B_NET[docker0 bridge]
B_C2[Container 2] --- B_NET
B_NET --- B_HOST[Host Network Stack]
end
subgraph "Host Network"
H_C[Container] --- H_HOST[Host Network Stack]
end
subgraph "None Network"
N_C[Container - 無網路]
end
| 網路類型 | 說明 | 適用場景 |
|---|---|---|
| bridge | 預設網路,Container 透過虛擬橋接器連接 | 單機多容器通訊 |
| host | Container 直接使用主機網路 | 需要最高網路效能 |
| none | 無網路連接 | 安全隔離需求 |
| overlay | 跨主機容器通訊 | Docker Swarm 叢集 |
| macvlan | 分配真實 MAC 地址 | 需要直接連接實體網路 |
網路基本操作¶
Docker 網路管理
# 列出所有網路
docker network ls
# 檢視網路詳細資訊
docker network inspect bridge
# 建立自訂網路
docker network create my-network
# 建立指定子網路的網路
docker network create \
--driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
my-custom-network
# 刪除網路
docker network rm my-network
# 清理未使用的網路
docker network prune
容器連接網路¶
容器網路連接
# 執行容器時指定網路
docker run -d --name app1 --network my-network nginx
# 將運行中的容器連接到網路
docker network connect my-network container-name
# 將容器從網路斷開
docker network disconnect my-network container-name
容器間通訊¶
使用自訂網路實現容器間通訊
在同一個自訂網路中的容器,可以使用**容器名稱**作為 hostname 互相存取。
容器間通訊範例
# 建立網路
docker network create app-network
# 啟動 MySQL Container
docker run -d \
--name mysql-db \
--network app-network \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8
# 啟動應用程式 Container,使用 mysql-db 作為資料庫主機
docker run -d \
--name my-app \
--network app-network \
-e DB_HOST=mysql-db \
-e DB_PASSWORD=secret \
my-application
# 測試連線
docker exec my-app ping mysql-db
Port 對應¶
Port Mapping
# 對應單一 Port
docker run -d -p 8080:80 nginx
# 對應多個 Port
docker run -d -p 8080:80 -p 8443:443 nginx
# 對應到所有介面的隨機 Port
docker run -d -P nginx
# 只對應到 localhost
docker run -d -p 127.0.0.1:8080:80 nginx
# 對應 UDP Port
docker run -d -p 53:53/udp dns-server
2.5 Docker Search¶
搜尋 Image¶
搜尋 Docker Hub
# 基本搜尋
docker search nginx
# 限制結果數量
docker search --limit 5 nginx
# 只顯示官方 Image
docker search --filter is-official=true nginx
# 只顯示自動建置的 Image
docker search --filter is-automated=true nginx
# 根據星星數過濾
docker search --filter stars=100 nginx
搜尋結果說明:
| 欄位 | 說明 |
|---|---|
| NAME | Image 名稱 |
| DESCRIPTION | 描述 |
| STARS | 星星數(人氣指標) |
| OFFICIAL | 是否為官方 Image |
| AUTOMATED | 是否自動建置 |
選擇 Image 的建議
- 優先選擇**官方 Image**(OFFICIAL = [OK])
- 查看**星星數**和**下載次數**
- 到 Docker Hub 網站查看**文件**和**更新頻率**
- 檢查 Image 的**安全掃描結果**
2.6 Docker Pull¶
拉取 Image¶
拉取 Image
# 拉取最新版本(預設 latest tag)
docker pull nginx
# 拉取特定版本
docker pull nginx:1.25
# 拉取特定版本(alpine 輕量版)
docker pull nginx:alpine
# 從其他 Registry 拉取
docker pull quay.io/bitnami/nginx
# 拉取特定平台的 Image
docker pull --platform linux/amd64 nginx
Image 標籤(Tag)¶
graph LR
N[nginx] --> L[latest]
N --> V1[1.25]
N --> V2[1.25.3]
N --> A[alpine]
N --> VA[1.25-alpine]
避免使用 latest
latest標籤會隨時間變化- 生產環境應使用**明確版本號**
- 例如:
nginx:1.25.3而非nginx:latest
管理本地 Image¶
Image 管理指令
# 列出本地 Image
docker images
# 列出所有 Image(包含中間層)
docker images -a
# 檢視 Image 詳細資訊
docker image inspect nginx
# 檢視 Image 歷史(分層)
docker history nginx
# 刪除 Image
docker rmi nginx
# 刪除未使用的 Image
docker image prune
# 刪除所有未使用的 Image(包含未標記的)
docker image prune -a
2.7 Docker Push¶
推送 Image 到 Registry¶
推送到 Docker Hub¶
推送到 Docker Hub
# 1. 登入 Docker Hub
docker login
# 2. 為 Image 加上標籤(必須包含使用者名稱)
docker tag my-app:v1 username/my-app:v1
# 3. 推送 Image
docker push username/my-app:v1
# 4. 登出(選用)
docker logout
推送到私有 Registry¶
推送到私有 Registry
# 1. 登入私有 Registry
docker login my-registry.example.com
# 2. 為 Image 加上私有 Registry 標籤
docker tag my-app:v1 my-registry.example.com/my-app:v1
# 3. 推送
docker push my-registry.example.com/my-app:v1
Image 命名規則
例如:
nginx=docker.io/library/nginx:latestbitnami/nginx=docker.io/bitnami/nginx:latestgcr.io/project/app:v1
標籤管理¶
Image 標籤操作
# 加上新標籤
docker tag my-app:v1 my-app:latest
docker tag my-app:v1 my-app:stable
# 推送多個標籤
docker push my-app:v1
docker push my-app:latest
docker push my-app:stable
2.8 使用 Docker 架設 WordPress + MySQL¶
Lab 實作目標¶
部署一個完整的 WordPress 網站,包含:
- MySQL 資料庫容器
- WordPress 應用程式容器
- 使用 Docker Network 連接
- 使用 Volume 持久化資料
架構圖¶
graph TB
subgraph "Docker 環境"
subgraph "wp-network"
WP[WordPress<br/>Port: 8080] -->|連接| DB[(MySQL<br/>Port: 3306)]
end
WP_VOL[wordpress-data<br/>Volume] --> WP
DB_VOL[mysql-data<br/>Volume] --> DB
end
User[使用者] -->|http://localhost:8080| WP
實作步驟¶
步驟 1:建立網路¶
步驟 2:啟動 MySQL 容器¶
啟動 MySQL
docker run -d \
--name wp-mysql \
--network wp-network \
-v mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=rootpassword \
-e MYSQL_DATABASE=wordpress \
-e MYSQL_USER=wpuser \
-e MYSQL_PASSWORD=wppassword \
mysql:8.0
MySQL 環境變數說明
| 環境變數 | 說明 |
|---|---|
MYSQL_ROOT_PASSWORD |
root 密碼(必填) |
MYSQL_DATABASE |
自動建立的資料庫 |
MYSQL_USER |
自動建立的使用者 |
MYSQL_PASSWORD |
使用者密碼 |
步驟 3:啟動 WordPress 容器¶
啟動 WordPress
docker run -d \
--name wp-app \
--network wp-network \
-p 8080:80 \
-v wordpress-data:/var/www/html \
-e WORDPRESS_DB_HOST=wp-mysql:3306 \
-e WORDPRESS_DB_NAME=wordpress \
-e WORDPRESS_DB_USER=wpuser \
-e WORDPRESS_DB_PASSWORD=wppassword \
wordpress:latest
步驟 4:驗證部署¶
驗證容器狀態
# 檢查容器是否運行
docker ps
# 檢查容器日誌
docker logs wp-mysql
docker logs wp-app
# 測試 MySQL 連線
docker exec wp-mysql mysql -uwpuser -pwppassword -e "SHOW DATABASES;"
步驟 5:存取 WordPress¶
開啟瀏覽器,前往 http://localhost:8080,完成 WordPress 安裝精靈。
使用 Docker Compose(額外說明)¶
更簡潔的方式
使用 Docker Compose 可以將以上所有設定集中在一個檔案中。
docker-compose.yml
version: '3.8'
services:
db:
image: mysql:8.0
container_name: wp-mysql
volumes:
- mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppassword
networks:
- wp-network
wordpress:
image: wordpress:latest
container_name: wp-app
depends_on:
- db
ports:
- "8080:80"
volumes:
- wordpress-data:/var/www/html
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppassword
networks:
- wp-network
networks:
wp-network:
driver: bridge
volumes:
mysql-data:
wordpress-data:
使用 Docker Compose 啟動
# 啟動所有服務
docker compose up -d
# 檢視狀態
docker compose ps
# 檢視日誌
docker compose logs -f
# 停止並移除
docker compose down
# 停止並移除(包含 Volume)
docker compose down -v
清理資源¶
清理實作環境
# 停止容器
docker stop wp-app wp-mysql
# 刪除容器
docker rm wp-app wp-mysql
# 刪除網路
docker network rm wp-network
# 刪除 Volume(警告:會刪除所有資料)
docker volume rm mysql-data wordpress-data
常見問題¶
Q1:Container 啟動後立即退出怎麼辦?
診斷步驟:
# 檢視容器日誌
docker logs container-name
# 檢視容器詳細資訊
docker inspect container-name
# 檢視最後退出狀態
docker ps -a --filter "name=container-name"
常見原因:
- 啟動指令錯誤
- 環境變數缺失
- 依賴服務未就緒
- 設定檔錯誤
Q2:如何讓容器在主機重啟後自動啟動?
解決方案:使用 --restart 選項
Q3:Volume 資料如何備份?
解決方案:
Q4:如何查看 Docker 佔用的磁碟空間?
解決方案:
Q5:容器間無法通訊怎麼辦?
診斷步驟:
小結¶
本章節重點回顧:
- ✅ Registry 類型:Public Registry(如 Docker Hub)與 Private Registry(如 Harbor)
- ✅ Container 管理:run、exec、logs、inspect 等核心指令
- ✅ 持久化儲存:Volume(Docker 管理)vs Bind Mount(主機目錄)
- ✅ Docker 網路:bridge、host、none 網路類型,自訂網路實現容器間通訊
- ✅ Image 操作:search、pull、push、tag 完整流程
- ✅ 實作經驗:WordPress + MySQL 容器化部署