一張圖搞懂 Docker 常見語法:從零開始理解映像檔、容器與 Dockerfile
更新日期: 2025 年 3 月 13 日
本文為 Docker 指令細談,第 1 篇:
- 一張圖搞懂 Docker 常見語法:從零開始理解映像檔、容器與 Dockerfile 👈進度
- 初學者指南:Docker 服務 (Service) 與容器 (Container) 的區別
- Docker Compose:深入理解 docker compose exec 指令
- Django 爬蟲自動化:Docker 獨立運行 scraper.py
- 新手指南:如何設定 WSL 2(Ubuntu 20.04)並整合 Docker
- 時區資料庫(tzdata)是什麼?完整介紹與應用指南
graph TD subgraph "Dockerfile 文件" dockerfile["Dockerfile"] docker_build["docker build"] end subgraph "映像檔" image["Docker 映像檔"] docker_pull["docker pull"] docker_push["docker push"] docker_images["docker images"] docker_rmi["docker rmi"] docker_tag["docker tag"] end subgraph "容器" container["Docker 容器"] docker_run["docker run"] docker_ps["docker ps"] docker_stop["docker stop"] docker_start["docker start"] docker_rm["docker rm"] docker_exec["docker exec"] docker_logs["docker logs"] end subgraph "Docker Compose 文件" compose_file["docker-compose.yml"] compose_up["docker-compose up"] compose_up_build["docker-compose up --build"] compose_down["docker-compose down"] compose_rebuild["docker-compose rebuild"] end %% Dockerfile 到 映像檔 dockerfile -->|定義構建過程| docker_build docker_build -->|構建| image %% 映像檔相關操作 docker_pull -->|拉取| image image -->|推送| docker_push image -->|列出| docker_images image -->|刪除| docker_rmi image -->|重命名| docker_tag %% 映像檔到容器 image -->|創建並運行| docker_run docker_run -->|創建| container %% 容器相關操作 container -->|查看運行中| docker_ps container -->|停止| docker_stop container -->|啟動| docker_start container -->|刪除| docker_rm container -->|執行命令| docker_exec container -->|查看日誌| docker_logs %% Docker Compose 與其他組件的關係 compose_file -->|引用或自動查找| dockerfile compose_file -->|定義服務配置| compose_up compose_up -->|創建並啟動多個| container compose_up_build -->|觸發| docker_build compose_up_build -->|使用多個| dockerfile compose_up_build -->|構建多個| image compose_up_build -->|啟動多個| container compose_down -->|停止並刪除多個| container compose_rebuild -->|重新構建服務映像檔| image
Docker 作為現代軟體開發和部署的重要工具,徹底改變了我們構建和運行應用程式的方式。
對於初學者而言,Docker 的概念和指令可能看起來有些複雜。
本文將從 Docker 的三個核心概念:Dockerfile、映像檔(Image)和容器(Container)出發,詳細解釋它們之間的關係,以及相關的常用指令。
此外,我們還會探討 Docker Compose 這個強大的工具如何簡化多容器應用的管理。
無論你是剛開始接觸 Docker 的開發者,還是想深入了解 Docker 架構的使用者,這篇文章都能幫助你建立清晰的理解。
Docker 三大核心概念
Dockerfile:應用的藍圖
Dockerfile 是一個文本文件,包含了一系列指令,Docker 引擎會按照這些指令一步步構建映像檔。
它就像是烹飪食譜或建築藍圖,定義了你的應用環境應該包含哪些元素和如何配置這些元素。
1️⃣ Dockerfile 的基本結構
一個簡單的 Dockerfile 通常包含以下元素:
- 基礎映像檔(FROM 指令):指定從哪個映像檔開始構建
- 環境設置(ENV 指令):設置環境變數
- 檔案複製(COPY/ADD 指令):將本地檔案複製到映像檔中
- 安裝依賴(RUN 指令):在映像檔中執行命令,例如安裝套件
- 暴露連接埠(EXPOSE 指令):聲明容器監聽的連接埠
- 啟動命令(CMD/ENTRYPOINT 指令):指定容器啟動時要執行的命令
2️⃣ Dockerfile 相關指令
docker build
:根據 Dockerfile 構建映像檔- 用法:
docker build -t 映像檔名稱:標籤 .
-t
代表 tag(標籤) - 作用:讀取當前目錄下的 Dockerfile,並按照其中的指令構建一個新的映像檔
- 用法:
映像檔(Image):應用的靜態模板
映像檔是 Docker 容器的靜態模板,包含了運行應用所需的所有內容——代碼、運行環境、依賴庫、環境變數等。
映像檔是多層結構,每一層代表 Dockerfile 中的一個指令。
這種分層結構使得映像檔能夠被高效地共享和重用。
1️⃣ 映像檔的特性
- 不可變性:映像檔一旦構建完成,其內容不可改變
- 分層結構:每一層都建立在前一層之上,形成疊加效果
- 可共享:不同映像檔可以共享相同的底層,節省空間和傳輸時間
2️⃣ 映像檔相關指令
docker pull
:從遠程倉庫拉取映像檔- 用法:
docker pull 映像檔名稱:標籤
- 作用:從 Docker Hub 或其他註冊表下載指定的映像檔
- 用法:
docker push
:推送映像檔到遠程倉庫- 用法:
docker push 映像檔名稱:標籤
- 作用:將本地映像檔上傳到 Docker Hub 或其他註冊表
- 用法:
docker images
:列出本地所有映像檔- 用法:
docker images
- 作用:顯示本機上所有的 Docker 映像檔及其相關資訊
- 用法:
docker rmi
:刪除本地映像檔- 用法:
docker rmi 映像檔ID或映像檔名稱:標籤
- 作用:刪除指定的本地映像檔
- 用法:
docker tag
:為映像檔添加標籤- 用法:
docker tag 來源映像檔:標籤 目標映像檔:標籤
- 作用:創建一個指向來源映像檔的新標籤
- 用法:
容器(Container):應用的運行實例
容器是映像檔的運行實例,是 Docker 的核心。
容器提供了獨立的運行環境,包含應用和它所有的依賴,但共享主機的操作系統內核。
每個容器都是相互隔離的,保證了應用的安全和穩定運行。
1️⃣ 容器的特性
- 輕量級:容器共享主機的內核,而不是像虛擬機那樣需要完整的操作系統
- 隔離性:每個容器都在自己的命名空間中運行,不會互相影響
- 可移植性:容器包含了運行環境,可以在任何支持 Docker 的環境中一致地運行
- 短暫性:容器通常設計為臨時性的,可以輕易創建、停止、刪除
2️⃣ 容器相關指令
docker run
:創建並啟動容器- 用法:
docker run [選項] 映像檔 [命令] [參數]
- 作用:基於指定的映像檔創建一個新的容器並運行
- 常用選項:
-d
:在後台運行容器-p 主機連接埠:容器連接埠
:映射連接埠-v 主機路徑:容器路徑
:掛載數據卷--name 容器名稱
:指定容器名稱
- 用法:
docker ps
:列出運行中的容器- 用法:
docker ps
或docker ps -a
(列出所有容器,包括已停止的) - 作用:顯示當前運行中的容器
- 用法:
docker stop
:停止運行中的容器- 用法:
docker stop 容器ID或容器名稱
- 作用:優雅地停止指定的容器
- 用法:
docker start
:啟動已停止的容器- 用法:
docker start 容器ID或容器名稱
- 作用:啟動一個已停止的容器
- 用法:
docker rm
:刪除容器- 用法:
docker rm 容器ID或容器名稱
- 作用:刪除指定的容器
- 用法:
docker exec
:在運行中的容器中執行命令- 用法:
docker exec [選項] 容器ID或容器名稱 命令 [參數]
- 作用:在一個運行中的容器內執行命令
- 常用選項:
-it
:提供互動式的終端
- 用法:
docker logs
:查看容器日誌- 用法:
docker logs [選項] 容器ID或容器名稱
- 作用:獲取容器的日誌輸出
- 用法:
Docker Compose:多容器應用的管理工具
Docker Compose 簡介
Docker Compose 是一個用於定義和運行多容器 Docker 應用的工具。
使用 Docker Compose,你可以通過一個YAML文件配置應用的多個服務,然後使用一個命令就能創建並啟動所有服務。
Docker Compose 實質上是對基本 Docker 命令的高級封裝,特別適合開發、測試和臨時環境。
docker-compose.yml 文件
docker-compose.yml
是 Docker Compose 的核心配置文件,它定義了應用的服務、網絡和卷。
一個簡單的 docker-compose.yml 文件可能如下所示:
version: '3'
services:
web:
build: ./web
ports:
- "5000:5000"
volumes:
- ./web:/code
depends_on:
- db
db:
image: postgres
environment:
POSTGRES_PASSWORD: example
在這個例子中,我們定義了兩個服務:
web
:從當前目錄下的web
文件夾的 Dockerfile 構建db
:使用名為 postgres 的映像檔
Docker Compose 與核心概念的關係
Docker Compose 與 Dockerfile、映像檔和容器有著密切的關係:
- 與 Dockerfile 的關係:
- Docker Compose 可以通過
build
指令指定 Dockerfile 的位置 - 執行
docker-compose up --build
時,Docker Compose 會查找並使用相應服務的 Dockerfile
- Docker Compose 可以通過
- 與映像檔的關係:
- Docker Compose 可以使用已有的映像檔(通過
image
指令) - 也可以通過構建 Dockerfile 創建新的映像檔(通過
build
指令) docker-compose rebuild
可以重新構建服務的映像檔
- Docker Compose 可以使用已有的映像檔(通過
- 與容器的關係:
- Docker Compose 能夠創建、啟動、停止和刪除多個容器
- 還能管理這些容器之間的網絡連接和數據共享
Docker Compose 常用指令
docker-compose up
:創建並啟動所有服務- 用法:
docker-compose up [選項]
- 作用:啟動在
docker-compose.yml
中定義的所有服務 - 常用選項:
-d
:在後台運行--build
:在啟動服務前重新構建映像檔
- 用法:
docker-compose up --build
:構建映像檔並啟動容器- 用法:
docker-compose up --build [服務名稱]
- 作用:強制重新構建映像檔,然後啟動服務
- 用法:
docker-compose down
:停止並刪除所有服務- 用法:
docker-compose down [選項]
- 作用:停止並刪除由
docker-compose up
創建的容器、網絡 - 常用選項:
-v
:同時刪除 Docker Compose 管理的卷
- 用法:
docker-compose rebuild
:重新構建服務- 用法:
docker-compose rebuild [服務名稱]
- 作用:重新構建指定服務的映像檔
- 用法:
Docker 工作流實例
單容器應用的完整流程
讓我們通過一個簡單的 Web 應用例子,展示從 Dockerfile 到容器的完整流程:
- 創建 Dockerfile:
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
- 構建映像檔:
docker build -t my-web-app:1.0 .
- 運行容器:
docker run -d -p 3000:3000 --name my-app-container my-web-app:1.0
- 查看運行中的容器:
docker ps
- 停止容器:
docker stop my-app-container
- 刪除容器和映像檔:
docker rm my-app-container
docker rmi my-web-app:1.0
多容器應用的 Docker Compose 流程
現在,讓我們看一個使用 Docker Compose 管理多容器應用的例子:
- 創建 docker-compose.yml:
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
environment:
- DATABASE_URL=mongodb://db:27017/myapp
db:
image: mongo:4.4
volumes:
- mongodb_data:/data/db
volumes:
mongodb_data:
- 啟動所有服務:
docker-compose up -d
- 查看服務狀態:
docker-compose ps
- 查看服務日誌:
docker-compose logs web
- 停止並移除所有服務:
docker-compose down
Docker 最佳實踐指南
Dockerfile 優化:打造輕量、高效的映像檔
1️⃣ 使用官方映像檔作為基礎
官方映像檔經過安全審核,能確保穩定性並獲得社群支持。建議優先使用官方提供的映像檔,例如:
FROM python:3.10-slim
這樣能減少潛在的安全風險,並獲得較小的映像檔體積。
2️⃣ 合併 RUN
指令以減少映像檔層數
每個 RUN
指令都會新增一層映像檔,過多的層數會增加構建時間與映像檔大小。因此,應該合併多條 RUN
指令,並刪除不必要的暫存檔案:
RUN apt-get update && apt-get install -y curl git \
&& rm -rf /var/lib/apt/lists/*
這樣能確保映像檔精簡且高效。
3️⃣ 使用 .dockerignore
排除不必要的文件
在專案目錄中建立 .dockerignore
文件,可避免將無關的文件(如 node_modules
、.git
等)加入映像檔,提高構建效率:
node_modules/
.git/
*.log
4️⃣ 指定確切的版本標籤,而不是 latest
避免使用 latest
,因為它可能導致不可預測的版本變更。建議指定明確的版本號,例如:
FROM node:18.15.0
5️⃣ 最小化映像檔大小,移除不必要的依賴
可以使用 slim
或 alpine
版本來減少映像檔大小,例如:
FROM python:3.10-alpine
此外,安裝完必要的套件後,應刪除不必要的安裝文件與暫存資料,以減少最終映像檔的體積。
映像檔管理:維持整潔與高效的 Docker 環境
1️⃣ 定期清理未使用的映像檔
映像檔長期累積會佔用大量磁碟空間,可使用以下指令刪除未使用的映像檔:
docker image prune -a
2️⃣ 使用版本標籤管理不同版本的映像檔
推送映像檔時,應明確標記版本,以便管理與回溯:
docker tag my_app my_repo/my_app:v1.2.3
docker push my_repo/my_app:v1.2.3
3️⃣ 利用多階段構建減少最終映像檔大小
多階段構建可讓構建環境與運行環境分離,確保最終映像檔輕量化:
# 第一階段:構建應用程式
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install && npm run build
# 第二階段:使用輕量映像檔作為運行環境
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
4️⃣ 考慮使用私有註冊表存儲內部映像檔
若有內部映像檔,建議使用 私有 Docker Registry 來存放,以提升安全性與存取速度:
docker tag my_app my_registry.com/my_app:v1.0
docker push my_registry.com/my_app:v1.0
容器安全性考量
1️⃣ 以非 root 用戶運行應用
應避免使用 root
權限,降低安全風險:
RUN useradd -m appuser
USER appuser
2️⃣ 限制容器的資源使用
可透過 --memory
和 --cpus
限制容器的資源使用:
docker run --memory=512m --cpus=1 my_app
3️⃣ 避免在映像檔中存儲敏感資訊
應使用 環境變數 或 Docker Secrets 來管理敏感資料,例如 API 金鑰、密碼等。
4️⃣ 定期更新基礎映像檔
保持基礎映像檔為最新版本,避免因漏洞導致安全風險:
docker pull python:3.10-slim
Docker Compose 高級技巧
1️⃣ 使用環境變數在不同環境中重用配置
version: '3'
services:
web:
image: nginx
environment:
- APP_ENV=production
2️⃣ 利用 extends
特性重用配置
x-common: &common
restart: always
services:
web:
<<: *common
image: nginx
3️⃣ 使用 depends_on
和 healthcheck
確保服務順序
services:
db:
image: mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
retries: 5
app:
image: my_app
depends_on:
db:
condition: service_healthy
常見問題與解決方案
1️⃣ 映像檔構建問題
✅ 解決方案:檢查 Dockerfile 語法,確保網路連線正常,使用 --no-cache
強制重新構建:
docker build --no-cache -t my_app .
2️⃣ 容器之間無法通信
✅ 解決方案:確保容器在同一個網路內:
docker network create my_network
docker run --network=my_network my_app
3️⃣ 資料持久化問題
✅ 解決方案:使用 Volumes 或 Bind Mounts 來確保數據不會丟失:
docker run -v /my/data:/app/data my_app
4️⃣ Docker Compose 啟動順序問題
✅ 解決方案:使用 depends_on
和 healthcheck
確保服務正確啟動。
結語
通過本文,我們詳細探討了 Docker 的三大核心概念:Dockerfile、映像檔和容器,以及它們之間的關係和相關指令。
我們還介紹了 Docker Compose 如何簡化多容器應用的管理。
希望這些知識能幫助初學者建立對 Docker 的全面理解,並在實際工作中更有效地使用 Docker。
Docker 的學習是一個持續的過程,隨著你的使用經驗增加,你會發現更多高級技巧和最佳實踐。
建議你在理解這些基本概念後,嘗試在自己的項目中應用 Docker,這是掌握 Docker 最有效的方式。
記住,Docker 的核心價值在於它提供的一致性環境和簡化的部署流程。無論你是開發人員、系統管理員還是 DevOps 工程師,熟練掌握 Docker 都能顯著提高你的工作效率和應用的可靠性。