博客 / 詳情

返回

Docker 基礎入門:核心概念與架構原理

在雲計算與容器化技術飛速發展的今天,Docker 已經成為開發者必備的工具之一。無論是本地開發環境的一致性保障、持續集成/持續部署(CI/CD)的自動化落地,還是服務器資源的高效利用,Docker 都發揮着不可替代的作用。對於剛接觸容器技術的新手而言,想要快速上手 Docker,首先需要理清其核心概念與底層架構,這也是後續深入學習 Docker 進階用法、解決實際問題的基礎。本文將從 Docker 的起源與價值出發,詳細拆解核心概念,剖析底層架構,並搭配實用代碼示例,幫助大家從零入門 Docker,真正理解其工作原理與使用邏輯。

一、Docker 簡介:什麼是 Docker,為什麼要用它?

1.1 Docker 的定義

Docker 是一個開源的應用容器引擎,基於 Go 語言開發,遵循 Apache 2.0 開源協議。它能夠將應用程序及其依賴項打包到一個可移植的容器中,然後發佈到任何支持 Docker 的操作系統上,實現“一次打包,到處運行”的效果。與傳統的虛擬機技術不同,Docker 容器不依賴於底層操作系統的虛擬化,而是共享宿主機的內核,因此具有啓動速度快、資源佔用少、可移植性強等優勢。

1.2 Docker 的核心價值

在 Docker 出現之前,開發者常常面臨“開發環境能跑,生產環境跑不起來”的困境,核心原因在於開發環境、測試環境、生產環境的配置不一致,以及依賴項版本衝突等問題。Docker 的出現,正是為了解決這些痛點,其核心價值主要體現在以下幾個方面:
  • 環境一致性:將應用及其依賴(如編程語言、庫、配置文件等)打包成容器,容器在任何支持 Docker 的環境中運行時,都能保持一致的運行效果,徹底解決“環境不一致”問題。
  • 資源高效利用:Docker 容器共享宿主機內核,不需要像虛擬機那樣佔用獨立的內存、CPU 和操作系統資源,啓動時間通常在秒級,資源利用率遠高於虛擬機。
  • 可移植性強:容器可以在本地、服務器、雲平台之間自由遷移,只要目標環境支持 Docker,就能直接運行,無需修改任何配置。
  • 簡化部署與運維:通過 Docker 可以快速部署應用,實現自動化運維,減少人工操作,降低部署失誤的概率,同時便於應用的擴容與縮容。
  • 隔離性良好:每個容器都是獨立的運行環境,容器之間相互隔離,不會相互影響,避免了應用之間的衝突,提高了系統的穩定性和安全性。

1.3 Docker 與虛擬機的區別

很多新手會將 Docker 與虛擬機混淆,但兩者在底層實現、資源佔用、啓動速度等方面有本質區別,具體對比如下表所示:
對比維度
Docker 容器
虛擬機(VM)
底層實現
共享宿主機內核,基於容器化技術
虛擬化底層硬件,運行獨立操作系統
資源佔用
佔用資源少,輕量級
佔用資源多,重量級
啓動速度
秒級啓動
分鐘級啓動
隔離性
進程級隔離,隔離性較弱
系統級隔離,隔離性強
可移植性
強,可跨平台遷移
弱,依賴虛擬化軟件和底層系統
簡單來説,虛擬機是“模擬一個完整的操作系統”,而 Docker 容器是“模擬一個應用的運行環境”,兩者的定位不同,適用場景也不同。在實際開發中,通常會結合兩者的優勢,比如用虛擬機提供底層環境,用 Docker 容器部署應用。

二、Docker 核心概念:吃透這5個概念,入門就成功了一半

Docker 有5個核心概念,分別是:鏡像(Image)、容器(Container)、倉庫(Repository)、Dockerfile、Docker Compose。這5個概念是理解 Docker 工作流程的關鍵,下面逐一詳細講解,並搭配代碼示例,幫助大家快速掌握。

2.1 鏡像(Image):容器的“模板”

2.1.1 鏡像的定義

鏡像(Image)是 Docker 中最基礎的概念,它是一個只讀的模板,包含了運行應用程序所需的所有文件、依賴項、配置信息和操作系統內核。可以把鏡像理解為“容器的模板”,一個鏡像可以創建多個容器,就像一個類可以實例化多個對象一樣。
例如,一個 Nginx 鏡像,就包含了 Nginx 服務器的安裝文件、配置文件、依賴的庫文件等,通過這個鏡像,我們可以快速創建多個 Nginx 容器,每個容器都是獨立運行的 Nginx 服務。

2.1.2 鏡像的核心特性

  • 只讀性:鏡像一旦創建,就無法修改,只能通過創建新的鏡像來實現更新。
  • 分層存儲:Docker 鏡像採用分層存儲技術,每一層都是一個獨立的文件系統,層與層之間相互依賴。這種分層結構可以實現鏡像的複用,減少存儲空間的佔用。例如,多個鏡像可能共享同一個基礎層(如 Ubuntu 系統層),只需要存儲一次基礎層,就能被多個鏡像複用。
  • 可繼承性:可以基於一個已有的鏡像,通過添加新的層,創建一個新的鏡像。例如,基於 Ubuntu 鏡像,安裝 Python 環境,就能創建一個 Python 鏡像。

2.1.3 鏡像相關常用命令(代碼示例)

下面是鏡像操作的常用命令,所有命令均在 Linux 終端(或 Windows Docker Desktop 終端)中執行,大家可以直接複製執行,感受鏡像的操作流程。
# 1. 拉取鏡像(從 Docker Hub 拉取官方鏡像)
# 拉取最新版 Nginx 鏡像
docker pull nginx:latest
# 拉取指定版本的 Nginx 鏡像(如 1.24.0)
docker pull nginx:1.24.0

# 2. 查看本地所有鏡像
docker images
# 輸出示例:
# REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
# nginx        latest    605c77e624dd   2 weeks ago    142MB
# nginx        1.24.0    08393e824c32   2 months ago   141MB

# 3. 查看鏡像詳細信息
docker inspect nginx:latest

# 4. 給鏡像打標籤(便於區分鏡像版本)
docker tag nginx:latest my-nginx:v1.0

# 5. 刪除本地鏡像
# 刪除指定標籤的鏡像
docker rmi nginx:1.24.0
# 強制刪除鏡像(如果鏡像已被容器使用)
docker rmi -f nginx:latest

# 6. 保存鏡像為本地文件(便於遷移)
docker save -o nginx.tar nginx:latest

# 7. 加載本地鏡像文件
docker load -i nginx.tar

 

説明:Docker Hub 是 Docker 官方的鏡像倉庫,包含了大量官方和第三方的鏡像,我們可以通過 docker pull 命令直接拉取鏡像,無需自己手動構建。

2.2 容器(Container):鏡像的“實例”

2.2.1 容器的定義

容器(Container)是基於鏡像創建的可運行實例,是 Docker 中用於運行應用程序的載體。如果説鏡像是“模板”,那麼容器就是“模板實例化後的對象”,它可以被啓動、停止、重啓、刪除,並且容器之間相互隔離,擁有獨立的運行環境。
容器與鏡像的關係,就像進程與程序的關係:程序是靜態的代碼和資源,進程是程序的運行實例;鏡像也是靜態的模板,容器是鏡像的運行實例。

2.2.2 容器的核心特性

  • 可運行性:容器是基於鏡像創建的,包含了應用程序的運行環境,能夠直接啓動並運行應用。
  • 可寫性:容器在運行過程中,會在鏡像的只讀層之上添加一個可寫層,所有對容器的修改(如創建文件、修改配置)都會保存在這個可寫層中,不會影響原始鏡像。
  • 隔離性:每個容器都有自己獨立的網絡、進程、文件系統,與其他容器和宿主機隔離,避免相互干擾。
  • 輕量級:容器共享宿主機內核,不需要佔用獨立的操作系統資源,啓動速度快,資源佔用少。

2.2.3 容器相關常用命令(代碼示例)

容器的操作是 Docker 日常使用中最頻繁的,下面的命令涵蓋了容器的創建、啓動、停止、刪除、進入等常用操作,建議大家實際操作一遍,加深理解。
# 1. 基於鏡像創建並啓動容器
# 格式:docker run [選項] 鏡像名:標籤 [容器內執行的命令]
# 示例1:啓動 Nginx 容器,後台運行,映射宿主機80端口到容器80端口
docker run -d -p 80:80 --name my-nginx nginx:latest
# 選項説明:
# -d:後台運行容器(守護進程模式)
# -p 80:80:將宿主機的80端口映射到容器的80端口(宿主機端口:容器端口)
# --name my-nginx:給容器命名為 my-nginx,便於後續操作

# 示例2:啓動 Ubuntu 容器,進入交互模式(可以在容器內執行命令)
docker run -it --name my-ubuntu ubuntu:latest /bin/bash
# 選項説明:
# -it:交互模式(-i 保持標準輸入打開,-t 分配偽終端)
# /bin/bash:容器啓動後執行的命令,進入 bash 終端

# 2. 查看正在運行的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a

# 3. 啓動、停止、重啓容器
# 啓動已停止的容器
docker start my-nginx
# 停止正在運行的容器
docker stop my-nginx
# 重啓容器
docker restart my-nginx

# 4. 進入正在運行的容器(交互模式)
# 方法1:exec 命令(推薦,不會影響容器的運行狀態)
docker exec -it my-nginx /bin/bash
# 方法2:attach 命令(進入容器後,退出會導致容器停止)
docker attach my-nginx

# 5. 查看容器日誌(用於排查問題)
docker logs my-nginx
# 實時查看日誌(類似 tail -f)
docker logs -f my-nginx

# 6. 查看容器詳細信息
docker inspect my-nginx

# 7. 刪除容器(需先停止容器,或強制刪除)
# 刪除已停止的容器
docker rm my-nginx
# 強制刪除正在運行的容器
docker rm -f my-nginx

# 8. 容器與宿主機之間複製文件
# 宿主機文件複製到容器內:docker cp 宿主機路徑 容器名:容器內路徑
docker cp /home/test.txt my-nginx:/usr/share/nginx/html
# 容器內文件複製到宿主機:docker cp 容器名:容器內路徑 宿主機路徑
docker cp my-nginx:/usr/share/nginx/html/index.html /home
實操驗證:執行 docker run -d -p 80:80 --name my-nginx nginx:latest 命令後,打開瀏覽器,訪問 http://localhost,如果能看到 Nginx 的默認歡迎頁面,説明容器啓動成功,端口映射生效。

 

2.3 倉庫(Repository):鏡像的“倉庫”

2.3.1 倉庫的定義

倉庫(Repository)是用於存儲和管理 Docker 鏡像的地方,類似於代碼倉庫(如 GitHub),我們可以將自己構建的鏡像推送到倉庫,也可以從倉庫拉取別人上傳的鏡像。
倉庫分為公有倉庫和私有倉庫:
  • 公有倉庫:對外開放,所有人都可以拉取鏡像,最常用的是 Docker Hub(https://hub.docker.com/),包含了大量官方鏡像和第三方鏡像。
  • 私有倉庫:僅對特定用户或團隊開放,用於存儲企業內部的鏡像,避免敏感鏡像泄露,常用的私有倉庫有 Docker Registry、Harbor 等。

2.3.2 倉庫相關常用命令(代碼示例)

# 1. 登錄 Docker Hub(需先註冊 Docker Hub 賬號)
docker login
# 輸入用户名和密碼,登錄成功後,即可推送鏡像到 Docker Hub

# 2. 推送鏡像到 Docker Hub(需先給鏡像打標籤,標籤格式:用户名/鏡像名:標籤)
# 示例:給本地 Nginx 鏡像打標籤,推送至自己的 Docker Hub 倉庫
docker tag nginx:latest your-username/my-nginx:v1.0
docker push your-username/my-nginx:v1.0

# 3. 從 Docker Hub 拉取自己推送的鏡像
docker pull your-username/my-nginx:v1.0

# 4. 退出 Docker Hub 登錄
docker logout

# 5. 私有倉庫相關操作(以 Docker Registry 為例)
# 拉取私有倉庫鏡像(需先登錄私有倉庫)
docker login private-registry-url:port
docker pull private-registry-url:port/my-nginx:v1.0
# 推送鏡像到私有倉庫
docker tag nginx:latest private-registry-url:port/my-nginx:v1.0
docker push private-registry-url:port/my-nginx:v1.0

 

2.4 Dockerfile:構建鏡像的“腳本”

2.4.1 Dockerfile 的定義

Dockerfile 是一個文本文件,包含了一系列的指令(Instruction),用於描述如何構建一個 Docker 鏡像。通過 Dockerfile,我們可以自定義鏡像的內容,比如安裝特定的軟件、配置環境變量、複製文件等,實現鏡像的自動化構建。
Dockerfile 的核心作用是“標準化鏡像構建流程”,只要有 Dockerfile,任何人都可以按照相同的步驟構建出相同的鏡像,避免了手動構建鏡像的繁瑣和誤差。

2.4.2 Dockerfile 常用指令

Dockerfile 中的指令有固定的格式,通常以大寫字母開頭,後面跟隨具體的參數,常用指令如下:
  • FROM:指定基礎鏡像,是 Dockerfile 的第一個指令,用於指定構建鏡像的基礎模板。例如 FROM ubuntu:latest,表示基於最新版的 Ubuntu 鏡像構建新鏡像。
  • WORKDIR:指定容器運行時的工作目錄,後續的指令(如 RUN、COPY)都會在這個目錄下執行。例如 WORKDIR /app,表示工作目錄為 /app。
  • COPY:將宿主機的文件或目錄複製到鏡像中。例如 COPY ./app.py /app,表示將宿主機當前目錄下的 app.py 文件複製到鏡像的 /app 目錄下。
  • ADD:與 COPY 類似,也用於複製文件,但支持解壓壓縮文件和從 URL 下載文件。例如 ADD ./app.tar.gz /app,表示將宿主機的 app.tar.gz 壓縮文件複製到鏡像的 /app 目錄,並自動解壓。
  • RUN:在構建鏡像時執行命令,用於安裝軟件、配置環境等。例如 RUN apt update && apt install -y python3,表示更新軟件源並安裝 Python3。
  • ENV:設置環境變量,在鏡像構建和容器運行時都生效。例如 ENV PYTHONPATH=/app,表示設置 Python 的環境變量。
  • EXPOSE:聲明容器運行時監聽的端口,只是一個聲明,不會自動映射端口,需要在 docker run 時使用 -p 選項進行端口映射。例如 EXPOSE 8080,表示容器監聽 8080 端口。
  • CMD:指定容器啓動時執行的命令,一個 Dockerfile 中只能有一個 CMD 指令,若有多個,只有最後一個生效。例如 CMD ["python3", "app.py"],表示容器啓動時執行 python3 app.py 命令。
  • ENTRYPOINT:與 CMD 類似,也用於指定容器啓動時執行的命令,但 ENTRYPOINT 的命令不會被 docker run 後面的命令覆蓋,而 CMD 會被覆蓋。例如 ENTRYPOINT ["python3"],如果執行docker run -it my-image app.py,則容器啓動時執行 python3 app.py。

2.4.3 Dockerfile 構建鏡像示例(代碼示例)

下面我們通過一個實際案例,使用 Dockerfile 構建一個 Python 應用鏡像,步驟如下:
  1. 創建一個工作目錄,新建 Dockerfile 文件和 Python 應用文件(app.py)。
  2. 編寫 Dockerfile 指令,定義鏡像的構建流程。
  3. 使用 docker build 命令構建鏡像。
  4. 基於構建好的鏡像啓動容器,驗證應用是否能正常運行。
# 1. 創建工作目錄並進入
mkdir python-app && cd python-app

# 2. 新建 app.py 文件(簡單的 Python Web 應用,使用 Flask 框架)
cat > app.py << EOF
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello Docker! This is a Python App."

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)
EOF

# 3. 新建 Dockerfile 文件,編寫構建指令
cat > Dockerfile << EOF
# 指定基礎鏡像(Python 3.10 官方鏡像)
FROM python:3.10-slim

# 設置工作目錄
WORKDIR /app

# 複製宿主機的 app.py 文件到鏡像的 /app 目錄
COPY app.py /app

# 安裝 Flask 依賴
RUN pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple

# 聲明容器監聽的端口
EXPOSE 8080

# 指定容器啓動時執行的命令
CMD ["python3", "app.py"]
EOF

# 4. 構建鏡像(-t 選項指定鏡像標籤,格式:鏡像名:標籤)
docker build -t my-python-app:v1.0 .
# 説明:最後的 "." 表示 Dockerfile 所在的當前目錄

# 5. 基於構建好的鏡像啓動容器,映射 8080 端口
docker run -d -p 8080:8080 --name my-python-app my-python-app:v1.0

# 6. 驗證應用是否正常運行(訪問 http://localhost:8080,查看是否返回指定內容)
curl http://localhost:8080
驗證結果:執行 curl http://localhost:8080 後,如果輸出 Hello Docker! This is a Python App.,説明鏡像構建成功,容器運行正常。

 

2.5 Docker Compose:多容器管理工具

2.5.1 Docker Compose 的定義

在實際開發中,一個應用往往需要多個容器協同工作,比如一個 Web 應用需要 Web 容器、數據庫容器、緩存容器等。如果手動一個個啓動、配置這些容器,會非常繁瑣,且容易出錯。Docker Compose 就是為了解決多容器管理問題而出現的工具。
Docker Compose 是 Docker 官方提供的多容器編排工具,基於 YAML 文件定義多個容器的配置(如鏡像、端口映射、環境變量、依賴關係等),通過一條命令就能啓動、停止、重啓所有相關容器,實現多容器的自動化管理。

2.5.2 Docker Compose 常用命令與示例(代碼示例)

首先需要安裝 Docker Compose(Docker Desktop 已內置 Docker Compose,Linux 系統需手動安裝),然後通過編寫 docker-compose.yml 文件定義多容器配置,最後使用 docker compose 命令進行操作。
下面以“Web 應用 + MySQL 數據庫”為例,演示 Docker Compose 的使用:
# 1. 創建工作目錄並進入
mkdir web-mysql && cd web-mysql

# 2. 新建 docker-compose.yml 文件(核心配置文件)
cat > docker-compose.yml << EOF
version: '3.8'  # 指定 Docker Compose 的版本

# 定義所有服務(容器)
services:
  # 定義 Web 服務(基於之前構建的 my-python-app 鏡像)
  web:
    image: my-python-app:v1.0  # 指定鏡像
    ports:
      - "8080:8080"  # 端口映射
    depends_on:
      - mysql  # 依賴 mysql 服務,mysql 啓動後再啓動 web
    environment:  # 設置環境變量(用於連接 MySQL)
      - MYSQL_HOST=mysql
      - MYSQL_USER=root
      - MYSQL_PASSWORD=123456
      - MYSQL_DB=test_db
    restart: always  # 容器異常退出時自動重啓

  # 定義 MySQL 服務(使用官方 MySQL 鏡像)
  mysql:
    image: mysql:8.0  # 指定 MySQL 鏡像版本
    ports:
      - "3306:3306"  # 端口映射,宿主機 3306 端口映射到容器 3306 端口
    environment:  # 設置 MySQL 環境變量
      - MYSQL_ROOT_PASSWORD=123456  # 根密碼
      - MYSQL_DATABASE=test_db  # 初始化數據庫
    volumes:
      - mysql-data:/var/lib/mysql  # 數據卷掛載,持久化 MySQL 數據
    restart: always

# 定義數據卷(用於持久化數據,避免容器刪除後數據丟失)
volumes:
  mysql-data:
EOF

# 3. 啓動所有服務(容器)
docker compose up -d
# 説明:-d 表示後台運行,會自動創建並啓動 web 和 mysql 兩個容器

# 4. 查看所有服務狀態
docker compose ps

# 5. 查看服務日誌(可指定服務名,如查看 web 服務日誌)
docker compose logs web
# 查看所有服務日誌
docker compose logs -f

# 6. 停止所有服務(容器不會刪除)
docker compose stop

# 7. 啓動已停止的服務
docker compose start

# 8. 停止並刪除所有服務(包括容器、網絡、數據卷)
docker compose down
# 保留數據卷(只刪除容器和網絡)
docker compose down -v

 

説明:數據卷(volumes)的作用是持久化數據,MySQL 容器中的數據會存儲在宿主機的指定目錄下,即使容器被刪除,數據也不會丟失。depends_on 選項用於定義服務之間的依賴關係,確保 MySQL 服務先啓動,Web 服務再啓動,避免 Web 服務因無法連接 MySQL 而報錯。

三、Docker 架構原理:理解 Docker 是如何工作的

掌握了 Docker 的核心概念後,我們需要深入瞭解 Docker 的底層架構,理解 Docker 各個組件之間的交互流程,這樣才能更好地排查問題、優化容器配置。Docker 採用的是客户端-服務器(C/S)架構,主要由客户端(Docker Client)、服務器端(Docker Daemon)、容器運行時(Container Runtime)、鏡像倉庫(Registry)和網絡、存儲等組件組成。

3.1 Docker 整體架構圖

Docker 的整體架構可以分為以下幾個核心組件,各組件之間相互協作,完成鏡像的拉取、容器的創建與運行等操作:
  • Docker 客户端(Docker Client):用户與 Docker 交互的入口,通過命令行或圖形界面(如 Docker Desktop)向 Docker 服務器發送指令(如 docker run、docker build 等),客户端不直接執行操作,而是將指令發送給 Docker 守護進程,由守護進程完成具體操作。
  • Docker 守護進程(Docker Daemon):運行在宿主機上的後台進程(daemon 進程),負責監聽客户端發送的指令,執行鏡像拉取、鏡像構建、容器創建、容器啓動等核心操作,是 Docker 架構的核心。
  • 容器運行時(Container Runtime):負責容器的實際運行,Docker 最初使用的是 LXC(Linux Containers)作為容器運行時,後來推出了自研的 runc,目前 Docker 默認使用 runc 作為容器運行時。容器運行時的核心作用是創建和管理容器的進程、文件系統、網絡等,實現容器的隔離與運行。
  • 鏡像倉庫(Registry):用於存儲和管理 Docker 鏡像,客户端通過 Docker 守護進程與倉庫交互,完成鏡像的拉取和推送。
  • 網絡(Network):Docker 提供了多種網絡模式,用於實現容器之間、容器與宿主機之間、容器與外部網絡之間的通信,確保容器的網絡隔離與連通性。
  • 存儲(Storage):Docker 提供了多種存儲驅動和數據卷機制,用於實現容器數據的持久化存儲,避免容器刪除後數據丟失。

3.2 Docker 核心組件詳解

3.2.1 Docker 客户端(Docker Client)

Docker 客户端是用户操作 Docker 的主要工具,支持命令行(docker 命令)、API 接口和圖形界面三種交互方式。用户輸入的每一條 docker 命令,本質上都是通過客户端向 Docker 守護進程發送一個 HTTP 請求,請求守護進程執行相應的操作。
例如,當用户執行 docker run nginx:latest 命令時,客户端會將該指令轉換為 HTTP 請求,發送給 Docker 守護進程,守護進程收到請求後,會先檢查本地是否有 nginx:latest 鏡像,如果沒有,則從 Docker Hub 拉取鏡像,然後基於鏡像創建並啓動容器,最後將執行結果返回給客户端。

3.2.2 Docker 守護進程(Docker Daemon)

Docker 守護進程(dockerd)是運行在宿主機上的後台進程,負責管理 Docker 的所有資源(鏡像、容器、網絡、存儲等),其核心功能包括:
  • 監聽客户端的請求(通過 Unix 套接字、TCP 端口等方式)。
  • 管理鏡像:拉取、構建、刪除、標籤等操作。
  • 管理容器:創建、啓動、停止、重啓、刪除、監控等操作。
  • 管理網絡:創建、刪除、配置 Docker 網絡,實現容器之間的通信。
  • 管理存儲:配置存儲驅動,管理數據卷,實現容器數據的持久化。
Docker 守護進程可以通過配置文件(如 /etc/docker/daemon.json)進行自定義配置,例如設置鏡像加速器、指定私有倉庫地址、配置存儲驅動等。

3.2.3 容器運行時(Container Runtime)

容器運行時是 Docker 實現容器隔離與運行的核心組件,負責創建容器的運行環境,包括進程隔離、文件系統隔離、網絡隔離等。Docker 遵循 OCI(Open Container Initiative,開放容器倡議)標準,OCI 標準定義了容器鏡像格式和容器運行時規範,確保不同容器引擎(如 Docker、containerd、Podman)之間的兼容性。
Docker 最初使用 LXC 作為容器運行時,後來為了更好地遵循 OCI 標準,推出了自研的 runc,runc 是一個輕量級的容器運行時,實現了 OCI 運行時規範,目前 Docker 默認使用 runc 作為容器運行時。此外,Docker 還支持 containerd 作為容器運行時,containerd 是一個更強大的容器運行時,負責鏡像管理、容器生命週期管理等功能,是 Docker 架構的重要組成部分。

3.2.4 網絡(Network)

Docker 提供了多種網絡模式,用於滿足不同場景下的容器通信需求,默認的網絡模式有以下4種:
  • bridge 模式(默認):這是 Docker 默認的網絡模式,每個容器都會被分配一個獨立的 IP 地址,容器之間通過 bridge 網絡相互通信,容器與宿主機之間通過端口映射實現通信。
  • host 模式:容器不使用獨立的網絡,而是共享宿主機的網絡,容器的 IP 地址與宿主機的 IP 地址相同,容器監聽的端口直接佔用宿主機的端口,無需進行端口映射。這種模式的優勢是網絡性能好,劣勢是容器與宿主機之間沒有網絡隔離。
  • none 模式:容器沒有網絡配置,無法與外界通信,通常用於不需要網絡的場景。
  • container 模式:一個容器共享另一個容器的網絡,兩個容器擁有相同的 IP 地址和網絡配置,通常用於需要兩個容器緊密協作的場景。
此外,Docker 還支持自定義網絡(如 bridge 網絡、overlay 網絡等),用於實現跨主機容器之間的通信,滿足分佈式應用的需求。

3.2.5 存儲(Storage)

Docker 的存儲機制主要分為兩種:鏡像存儲和容器存儲,核心目標是實現鏡像的分層存儲和容器數據的持久化。
  • 鏡像存儲:Docker 鏡像採用分層存儲技術,每一層都是一個只讀的文件系統,層與層之間相互依賴,這種分層結構可以實現鏡像的複用和增量更新。例如,基於 Ubuntu 鏡像構建 Python 鏡像時,只需要在 Ubuntu 鏡像的基礎上添加 Python 相關的層,無需重新存儲整個 Ubuntu 鏡像,節省存儲空間。
  • 容器存儲:容器在運行過程中,會在鏡像的只讀層之上添加一個可寫層,所有對容器的修改都會保存在這個可寫層中。當容器被刪除時,這個可寫層也會被刪除,容器內的數據會丟失。為了實現數據持久化,Docker 提供了數據卷(Volumes)和綁定掛載(Bind Mounts)兩種方式,將容器內的目錄與宿主機的目錄關聯起來,容器內的數據會同步到宿主機,即使容器被刪除,數據也不會丟失。
Docker 支持多種存儲驅動(如 overlay2、devicemapper、aufs 等),不同的存儲驅動在性能、穩定性等方面有不同的特點,其中 overlay2 是目前 Docker 默認的存儲驅動,適用於大多數場景。

3.3 Docker 工作流程詳解(以容器啓動為例)

為了更好地理解 Docker 的架構原理,我們以“啓動一個 Nginx 容器”為例,詳細拆解 Docker 的工作流程,看看各個組件之間是如何協同工作的:
  1. 用户在 Docker 客户端執行 docker run -d -p 80:80 nginx:latest 命令,客户端將該指令轉換為 HTTP 請求,發送給 Docker 守護進程。
  2. Docker 守護進程收到請求後,首先檢查本地鏡像倉庫中是否存在 nginx:latest 鏡像。
  3. 如果本地沒有該鏡像,Docker 守護進程會向 Docker Hub(默認倉庫)發送請求,拉取 nginx:latest 鏡像到本地。
  4. 鏡像拉取完成後,Docker 守護進程調用容器運行時(runc),基於 nginx 鏡像創建一個容器,分配容器 ID、網絡地址、文件系統等資源,並在鏡像的只讀層之上添加一個可寫層。
  5. Docker 守護進程配置容器的網絡,將宿主機的 80 端口映射到容器的 80 端口,確保外部能夠訪問容器內的 Nginx 服務。
  6. 容器創建完成後,Docker 守護進程啓動容器,執行鏡像中定義的啓動命令(CMD 指令),Nginx 服務開始運行。
  7. Docker 守護進程將容器的運行狀態(如容器 ID、啓動時間、端口映射等)返回給 Docker 客户端,用户可以通過 docker ps 命令查看容器狀態。
整個流程中,Docker 客户端負責接收用户指令,Docker 守護進程負責協調各個組件完成具體操作,容器運行時負責容器的實際運行,鏡像倉庫負責提供鏡像,網絡和存儲組件負責保障容器的通信和數據持久化,各個組件協同工作,實現了容器的快速創建和運行。

四、Docker 實戰:常見問題與解決方案

在實際使用 Docker 的過程中,新手常常會遇到一些問題,下面整理了幾個常見問題及解決方案,幫助大家快速排查問題,順利上手 Docker。

4.1 問題1:拉取鏡像速度慢

原因:默認的 Docker Hub 倉庫位於國外,國內訪問速度較慢。
解決方案:配置國內鏡像加速器(如阿里雲、網易雲等),步驟如下:
# 1. 編輯 Docker 守護進程配置文件
sudo vi /etc/docker/daemon.json

# 2. 添加鏡像加速器配置(以阿里云為例,需替換為自己的加速器地址)
{
  "registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
}

# 3. 重啓 Docker 服務,使配置生效
sudo systemctl daemon-reload
sudo systemctl restart docker

# 4. 驗證配置是否生效
docker info
# 查看輸出中是否有 "Registry Mirrors" 字段,顯示配置的加速器地址即生效

 

4.2 問題2:容器啓動失敗,提示端口被佔用

原因:容器要映射的宿主機端口已經被其他進程(或其他容器)佔用。
解決方案:
  • 方法1:更換宿主機端口,例如將 80 端口改為 8080,命令:docker run -d -p 8080:80 nginx:latest
  • 方法2:停止佔用該端口的進程或容器,例如查看 80 端口占用情況:netstat -tuln | grep 80,然後停止對應的進程或容器。

4.3 問題3:容器內無法訪問外部網絡

原因:Docker 網絡配置異常,或宿主機防火牆阻止了容器的網絡訪問。
解決方案:
  • 檢查 Docker 網絡是否正常:docker network ls,確保 bridge 網絡正常。
  • 重啓 Docker 服務:sudo systemctl restart docker
  • 關閉宿主機防火牆(臨時測試):sudo systemctl stop firewalld(CentOS 系統),或 sudo ufw disable(Ubuntu 系統)。

4.4 問題4:容器刪除後,數據丟失

原因:容器內的數據存儲在可寫層中,容器刪除後,可寫層被刪除,數據丟失。
解決方案:使用數據卷(Volumes)或綁定掛載(Bind Mounts)實現數據持久化,參考 2.5 節 Docker Compose 示例中的數據卷配置。

五、總結與進階學習建議

5.1 總結

本文圍繞 Docker 基礎入門,詳細講解了 Docker 的核心概念(鏡像、容器、倉庫、Dockerfile、Docker Compose)、底層架構(客户端、守護進程、容器運行時等組件),並搭配了大量實用的代碼示例,幫助大家從零掌握 Docker 的基本使用和工作原理。
核心要點回顧:
  • 鏡像:只讀的容器模板,採用分層存儲,可複用、可繼承。http://www.jaynscott.com/news/khc91vlh
  • 容器:鏡像的運行實例,可啓動、停止、重啓,具有隔離性和輕量級特性。http://www.jaynscott.com/news/khc9wa1vlh
  • 倉庫:存儲和管理鏡像的地方,分為公有倉庫和私有倉庫。http://www.jaynscott.com/news/khc91vlhbg
  • Dockerfile:構建鏡像的腳本,通過指令標準化鏡像構建流程。http://www.jaynscott.com/news/khc91vlhwae
  • Docker Compose:多容器管理工具,通過 YAML 文件實現多容器的自動化編排。http://www.jaynscott.com/news/khc91vlhwae
  • Docker 架構:C/S 架構,核心組件包括客户端、守護進程、容器運行時、倉庫、網絡、存儲,各組件協同工作,實現容器的快速創建和運行。

5.2 進階學習建議

如果想要進一步深入學習 Docker,可以從以下幾個方向入手:
  • Docker 進階特性:學習 Docker 網絡高級配置(如 overlay 網絡、macvlan 網絡)、存儲驅動原理、容器編排高級技巧等。
  • 容器編排工具:學習 Kubernetes(K8s),K8s 是目前最流行的容器編排平台,能夠實現容器的大規模部署、自動擴縮容、故障自愈等功能,是 Docker 進階的核心方向。
  • CI/CD 集成:學習如何將 Docker 與 CI/CD 工具(如 Jenkins、GitLab CI)集成,實現應用的自動化構建、測試、部署。
  • 生產環境部署:學習 Docker 在生產環境中的最佳實踐,如容器監控(Prometheus + Grafana)、日誌收集(ELK 棧)、安全配置等。
Docker 作為容器化技術的代表,已經成為雲計算、微服務、DevOps 領域的核心工具,掌握 Docker 不僅能提高開發和部署效率,還能為後續學習更高級的容器技術打下堅實的基礎。希望本文能幫助大家順利入門 Docker,在實際實踐中不斷提升自己的技術能力。
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.