一張圖搞懂 Docker 常見語法:從零開始理解映像檔、容器與 Dockerfile

更新日期: 2025 年 3 月 13 日

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 psdocker 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 可以使用已有的映像檔(通過 image 指令)
    • 也可以通過構建 Dockerfile 創建新的映像檔(通過 build 指令)
    • docker-compose rebuild 可以重新構建服務的映像檔
  • 與容器的關係
    • 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 到容器的完整流程:

  1. 創建 Dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
  1. 構建映像檔
docker build -t my-web-app:1.0 .
  1. 運行容器
docker run -d -p 3000:3000 --name my-app-container my-web-app:1.0
  1. 查看運行中的容器
docker ps
  1. 停止容器
docker stop my-app-container
  1. 刪除容器和映像檔
docker rm my-app-container
docker rmi my-web-app:1.0

多容器應用的 Docker Compose 流程

現在,讓我們看一個使用 Docker Compose 管理多容器應用的例子:

  1. 創建 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:
  1. 啟動所有服務
docker-compose up -d
  1. 查看服務狀態
docker-compose ps
  1. 查看服務日誌
docker-compose logs web
  1. 停止並移除所有服務
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️⃣ 最小化映像檔大小,移除不必要的依賴

可以使用 slimalpine 版本來減少映像檔大小,例如:

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_onhealthcheck 確保服務順序

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️⃣ 資料持久化問題

解決方案:使用 VolumesBind Mounts 來確保數據不會丟失:

docker run -v /my/data:/app/data my_app

4️⃣ Docker Compose 啟動順序問題

解決方案:使用 depends_onhealthcheck 確保服務正確啟動。


結語

通過本文,我們詳細探討了 Docker 的三大核心概念:Dockerfile、映像檔和容器,以及它們之間的關係和相關指令。

我們還介紹了 Docker Compose 如何簡化多容器應用的管理。

希望這些知識能幫助初學者建立對 Docker 的全面理解,並在實際工作中更有效地使用 Docker。

Docker 的學習是一個持續的過程,隨著你的使用經驗增加,你會發現更多高級技巧和最佳實踐。

建議你在理解這些基本概念後,嘗試在自己的項目中應用 Docker,這是掌握 Docker 最有效的方式。

記住,Docker 的核心價值在於它提供的一致性環境和簡化的部署流程。無論你是開發人員、系統管理員還是 DevOps 工程師,熟練掌握 Docker 都能顯著提高你的工作效率和應用的可靠性。

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *