從零開始掌握 Docker:核心命令與實踐指南
摘要: 本文系統整理了 Docker 的核心概念與常用命令,涵蓋鏡像管理、容器操作、數據存儲、網絡配置、Compose 編排以及 Dockerfile 構建等內容。通過清晰的命令示例和實用說明,幫助開發者快速上手 Docker 容器化技術,提升開發與部署效率。
關鍵詞: Docker, 容器化, 鏡像, 容器, Docker Compose, Dockerfile, 命令手冊
一、 Docker 鏡像管理
鏡像是 Docker 容器運行的基礎模板。
1. 搜索鏡像
在 Docker Hub 或其他注冊中心查找鏡像。
docker search nginx
2. 拉取鏡像
下載鏡像到本地倉庫。推薦指定標簽(如 :latest
, :alpine
)。
docker pull nginx # 拉取最新版 (latest)
docker pull nginx:latest # 顯式指定最新版
docker pull nginx:alpine # 拉取 Alpine Linux 精簡版
3. 查看本地鏡像
列出所有已下載的鏡像。
docker images
docker image ls # 等效命令
4. 刪除鏡像
移除不再需要的本地鏡像。注意: 依賴該鏡像的容器必須先刪除或停止。
docker rmi nginx:latest # 通過倉庫名:標簽刪除
docker rmi <鏡像ID> # 通過唯一鏡像 ID 刪除 (更精確)
二、 Docker 容器操作
容器是鏡像的運行實例。
1. 運行容器
啟動一個新的容器實例。
docker run nginx # 前臺運行 (會占用終端)
docker run -d --name mynginx nginx # 后臺運行 (-d) 并命名容器 (--name)
docker run -d --name myweb -p 8080:80 nginx # 后臺運行,并將容器 80 端口映射到宿主機 8080 端口 (-p)
# 常用選項:
# -d: 后臺運行 (detached mode)
# --name: 為容器指定一個易記的名稱
# -p <主機端口>:<容器端口>: 端口映射
# -it: 交互模式運行 (通常與 /bin/bash 結合進入容器)
# -e: 設置環境變量
# --restart=always: 容器退出時自動重啟
2. 查看容器狀態
docker ps # 查看正在運行的容器
docker ps -a # 查看所有容器 (包括已停止的)
docker ps -aq # 查看所有容器的 ID (只顯示 ID, 常用于批量操作)
3. 啟動/停止/重啟容器
docker start <容器名稱|容器ID> # 啟動已停止的容器
docker stop <容器名稱|容器ID> # 優雅停止運行中的容器 (發送 SIGTERM)
docker restart <容器名稱|容器ID> # 重啟容器
4. 查看容器資源使用與日志
docker stats <容器名稱|容器ID> # 實時查看容器的 CPU、內存、網絡、磁盤等資源使用情況
docker logs <容器名稱|容器ID> # 查看容器日志 (默認顯示已產生的日志)
docker logs -f <容器名稱|容器ID> # 持續跟蹤 (follow) 容器日志輸出 (類似 tail -f)
5. 進入運行中的容器
在運行的容器內啟動一個交互式 Shell(通常是 /bin/bash
或 /bin/sh
)。
docker exec -it mynginx /bin/bash
# -i: 保持 STDIN 打開
# -t: 分配一個偽終端 (TTY)
6. 刪除容器
移除不再需要的容器。注意: 正在運行的容器需要先停止或使用 -f
強制刪除。
docker rm <容器名稱|容器ID> # 刪除已停止的容器
docker rm -f <容器名稱|容器ID> # 強制刪除運行中的容器
docker rm $(docker ps -aq) # 批量刪除所有已停止的容器 (危險操作!)
三、 構建與分享自定義鏡像
1. 提交容器更改創建新鏡像
基于一個運行中的容器的當前狀態創建新的鏡像層。
docker commit -m "update index.html" mynginx mynginx:v1.0
# -m: 提交信息
# mynginx: 源容器名稱
# mynginx:v1.0: 新鏡像名稱:標簽
2. 保存鏡像為文件
將鏡像導出為 .tar
文件,方便離線傳輸或備份。
docker save -o mynginx.tar mynginx:v1.0
# -o: 指定輸出文件名
3. 從文件加載鏡像
從 .tar
文件恢復鏡像到本地倉庫。
docker load -i mynginx.tar
# -i: 指定輸入文件
4. 分享鏡像到 Docker Hub (或其他注冊中心)
-
登錄:
docker login # 默認登錄 Docker Hub, 提示輸入用戶名密碼
-
標記鏡像: 為本地鏡像添加符合目標倉庫規范的名稱(通常是
<DockerHub用戶名>/<倉庫名>:<標簽>
)。docker tag mynginx:v1.0 <你的DockerHub用戶名>/mynginx:v1.0
-
推送鏡像:
docker push <你的DockerHub用戶名>/mynginx:v1.0
四、 Docker 數據管理 (存儲卷 Volumes)
Docker 使用存儲卷 (Volumes) 或綁定掛載 (Bind Mounts) 來持久化容器數據,避免容器刪除后數據丟失。
1. 目錄掛載 (Bind Mounts)
將宿主機上的一個具體目錄直接掛載到容器內指定路徑。文件存在于宿主機文件系統上。
docker run -d -p 80:80 -v /宿主機/絕對路徑/nginxhtml:/usr/share/nginx/html --name myapp nginx
# -v /宿主機路徑:/容器路徑
- 優點: 直觀,方便在宿主機直接修改文件。
- 缺點: 依賴宿主機特定目錄結構,移植性稍差。
2. 卷掛載 (Volumes)
使用 Docker 管理的命名卷掛載到容器內路徑。卷存儲在 Docker 管理的區域 (/var/lib/docker/volumes/
),與容器生命周期解耦。
docker run -d -p 80:80 -v mynginxconf:/etc/nginx -v mynginxhtml:/usr/share/nginx/html --name myapp nginx
# -v 卷名:/容器路徑
- 優點: 移植性好,由 Docker 管理生命周期,備份/恢復方便。
- 缺點: 數據位置不如綁定掛載直觀。
3. 卷管理命令
docker volume ls # 列出所有 Docker 管理的卷
docker volume create myvolume # 創建一個新的命名卷
docker volume inspect myvolume # 查看指定卷的詳細信息 (包括其物理存儲位置 Mountpoint)
docker volume rm myvolume # 刪除一個不再使用的卷
# 注意:刪除容器時,使用 -v 選項可以同時刪除關聯的匿名卷 (未命名的卷)。命名卷需要顯式刪除。
五、 Docker 網絡管理
Docker 容器默認通過 docker0
虛擬網橋連接并相互隔離。
1. 查看容器網絡信息
docker container inspect <容器名稱|容器ID> # 查看容器詳細信息,包括其 IP 地址、網關、網絡配置等
2. 默認網絡 (docker0
) 的局限性
- 容器 IP 地址在重啟或重新創建后可能變化。
- 默認網絡不支持通過容器名稱進行服務發現(只能通過易變的 IP 地址訪問)。
3. 創建自定義網絡
自定義網絡解決了 docker0
的局限性:
- 為容器提供穩定的、可預測的 IP 地址段。
- 支持通過容器名稱作為主機名進行服務發現(容器間可以直接用名字通信)。
docker network create mynet # 創建一個名為 mynet 的自定義橋接網絡
docker network ls # 列出所有 Docker 網絡
4. 將容器連接到自定義網絡
docker run -d -p 8081:80 --name app1 --network mynet nginx
docker run -d -p 8082:80 --name app2 --network mynet nginx
- 現在
app1
可以直接通過ping app2
或http://app2
訪問app2
容器,反之亦然。 - 使用
docker inspect app1
查看其網絡配置,確認它連接到了mynet
并獲取了 IP。
5. 刪除網絡
注意: 只能刪除沒有容器連接的網絡。
docker network rm mynet
六、 使用 Docker Compose 編排多容器應用
Docker Compose 使用 YAML 文件 (docker-compose.yml
或 compose.yml
) 定義和運行多容器 Docker 應用。
1. 上線應用 (啟動服務)
在包含 compose.yaml
文件的目錄下運行:
docker compose -f compose.yaml up -d
# -f: 指定 Compose 文件 (默認為 compose.yml 或 docker-compose.yml 時可省略)
# -d: 后臺運行 (detached)
# up: 創建并啟動所有定義的服務、網絡、卷
- Compose 只會重建或重啟配置發生變化的容器(智能更新)。
2. 下線應用 (停止并清理)
docker compose -f compose.yaml down # 停止并移除容器、網絡 (默認保留卷和鏡像)
docker compose -f compose.yaml down --rmi all -v # 停止并移除容器、網絡,同時刪除所有相關鏡像(--rmi all)和卷(-v)
# --rmi all: 刪除 Compose 文件中定義的服務所使用的所有鏡像
# -v: 刪除 Compose 文件中定義的匿名卷和 compose 創建時指定的命名卷 (謹慎使用!)
七、 使用 Dockerfile 構建鏡像
Dockerfile 是一個文本文件,包含構建 Docker 鏡像所需的一系列指令。
常用 Dockerfile 指令
指令 | 說明 | 示例 |
---|---|---|
FROM | 指定基礎鏡像。 所有構建都以此為基礎。 | FROM openjdk:11 |
LABEL | 添加元數據 (鍵值對)。 如作者、描述、版本等。 | LABEL maintainer="liuqi@example.com" |
COPY | 復制文件/目錄。 從構建上下文復制到鏡像內。 | COPY ./app.jar /app/app.jar |
ADD | 類似 COPY ,但功能更多 (支持 URL、自動解壓 tar)。通常優先用 COPY。 | ADD https://example.com/file.tar.gz / |
WORKDIR | 設置工作目錄。 后續指令 (RUN , CMD , ENTRYPOINT , COPY , ADD ) 都在此目錄下執行。 | WORKDIR /app |
RUN | 執行命令。 在構建過程中運行命令并創建新的鏡像層。常用于安裝軟件包。 | RUN apt-get update && apt-get install -y curl |
EXPOSE | 聲明運行時容器監聽的端口。 只是一個文檔說明,實際映射需用 -p 。 | EXPOSE 8080 |
ENV | 設置環境變量。 在構建階段和運行階段都可用。 | ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk |
CMD | 指定容器啟動時的默認命令。 可以被 docker run 的命令覆蓋。 | CMD ["java", "-jar", "/app.jar"] |
ENTRYPOINT | 指定容器啟動時的主命令。 CMD 的內容通常作為其參數。更不易被覆蓋。 | ENTRYPOINT ["java", "-jar"] CMD ["/app.jar"] |
示例 Dockerfile (構建 Java 應用鏡像)
# 使用 OpenJDK 11 官方鏡像作為基礎
FROM openjdk:11# 添加維護者信息 (元數據)
LABEL author="liuqi" version="1.0"# 將構建上下文中的 app.jar 復制到鏡像根目錄下
COPY app.jar /app.jar# 聲明應用運行時監聽的端口
EXPOSE 8081# 設置容器啟動時執行的命令 (主進程)
ENTRYPOINT ["java", "-jar", "/app.jar"]
構建鏡像
在包含 Dockerfile
和 app.jar
的目錄下運行:
docker build -t myjavaapp:v1.0 .
# -t: 指定構建出的鏡像名稱和標簽 (myjavaapp:v1.0)
# . : 指定構建上下文路徑 (當前目錄),Dockerfile 和 COPY 的文件都相對于此路徑
八、 Docker 鏡像分層存儲機制
Docker 鏡像采用分層存儲 (Layer Storage) 機制,這是其高效性和輕量化的核心:
- Union File System (聯合文件系統): 如 AUFS, Overlay2 等。這些文件系統允許將多個目錄(稱為“層”)掛載到同一個虛擬目錄下。對用戶呈現的是一個單一的文件系統視圖。
- 只讀層 (Read-Only Layers):
- 鏡像由一系列只讀層疊加組成。
- 每一層代表 Dockerfile 中的一條指令(如
FROM
,RUN
,COPY
,ADD
)所引入的文件系統變化。 - 這些層是共享的。如果多個鏡像基于同一個基礎鏡像(如
ubuntu:latest
),那么它們共享基礎鏡像的所有只讀層,節省磁盤空間。
- 容器層 (Container Layer / Read-Write Layer):
- 當從鏡像啟動一個容器時,Docker 會在所有只讀層之上添加一個薄薄的讀寫層(通常稱為“容器層”或“可寫層”)。
- 容器運行時的所有文件寫入操作(創建、修改、刪除文件)都只發生在這個讀寫層中。
- 容器刪除時,這個讀寫層也會被丟棄(除非使用卷持久化數據)。
- 寫時復制 (Copy-on-Write - CoW):
- 如果一個容器需要修改只讀層中的某個文件(例如修改配置文件),CoW 機制會觸發:
- 該文件會從底層的只讀層復制到容器的讀寫層。
- 后續所有對該文件的修改都只發生在讀寫層的這個副本上。
- 底層的只讀文件保持不變。這保證了基礎鏡像的完整性和可共享性。
- 只有首次修改時才復制,優化了性能和存儲空間。
- 如果一個容器需要修改只讀層中的某個文件(例如修改配置文件),CoW 機制會觸發:
圖解:
+---------------------------------------------------+
| Container (myapp) |
| +-----------------------------------------------+ |
| | Read-Write Layer (R/W) | | (容器層 - 存儲運行時修改)
| +-----------------------------------------------+ |
| +-----------------------------------------------+ |
| | Read-Only Layer (n) | | (鏡像層 - 由 `RUN apt-get install` 添加)
| +-----------------------------------------------+ |
| ... |
| +-----------------------------------------------+ |
| | Read-Only Layer (2) | | (鏡像層 - 由 `COPY app.jar` 添加)
| +-----------------------------------------------+ |
| +-----------------------------------------------+ |
| | Read-Only Layer (1) | | (鏡像層 - 由 `FROM openjdk:11` 引入的基礎層)
| +-----------------------------------------------+ |
+---------------------------------------------------+(Union Mount Point - 呈現為單一文件系統視圖)
優勢:
- 高效構建: 構建鏡像時,如果某層及其之上的層沒有變化,Docker 會直接使用緩存中的層,極大加速構建過程。
- 節省空間: 多個鏡像和容器共享基礎層。
- 快速啟動: 啟動容器只需添加一個薄薄的讀寫層,無需復制整個文件系統。
- 鏡像復用: 公共基礎層只需下載一次。