Docker入門到精通:從零基礎到生產部署

前言:為什么你需要學習Docker?

想象一下,你開發了一個應用程序,在你的電腦上運行完美,但當你把它交給同事或部署到服務器時,卻出現了各種奇怪的問題。這就是著名的"在我機器上能運行"問題。

Docker就是解決這個問題的神器!它能確保你的應用在任何地方都能一致地運行,無論是在你的筆記本電腦、數據中心的服務器,還是在云平臺上。

學習路徑圖

安裝Docker
基礎操作
Dockerfile
Docker Compose
網絡與存儲
實戰項目
生產部署

本手冊專為零基礎小白設計,通過簡單易懂的語言、實用示例和互動練習,帶你從Docker小白成長為能夠熟練使用Docker的開發者。


第一章:Docker基礎概念

1.1 什么是Docker?

Docker是一種容器化技術,它允許你將應用程序及其所有依賴(代碼、庫、環境變量等)打包到一個輕量級、可移植的"容器"中。

類比理解

┌──────────────────────────────────────┐
│           宿主機操作系統             │
├───────────┬───────────┬──────────────┤
│ 容器1     │ 容器2     │ 容器3        │
│ (應用A)   │ (應用B)   │ (應用C)      │
│  ┌─────┐  │  ┌─────┐  │  ┌─────┐     │
│  │應用 │  │  │應用 │  │  │應用 │     │
│  │代碼 │  │  │代碼 │  │  │代碼 │     │
│  └─────┘  │  └─────┘  │  └─────┘     │
│  ┌─────┐  │  ┌─────┐  │  ┌─────┐     │
│  │依賴 │  │  │依賴 │  │  │依賴 │     │
│  │庫   │  │  │庫   │  │  │庫   │     │
│  └─────┘  │  └─────┘  │  └─────┘     │
└───────────┴───────────┴──────────────┘
  • 每個容器就像一艘集裝箱船上的標準集裝箱
  • 每個集裝箱(容器)都包含特定的貨物(應用程序)
  • 無論船(服務器)是什么類型,集裝箱都能被正確裝卸和運輸
  • 集裝箱之間相互隔離,互不影響

💡 小貼士:Docker容器共享宿主機的操作系統內核,而虛擬機需要運行完整的操作系統,因此容器更輕量、啟動更快。

1.2 Docker架構

Docker采用客戶端-服務端架構,主要組件包括:

┌───────────────────────────────────────────────────────────────┐
│                        宿主機                                 │
├───────────────────┬───────────────────────────┬───────────────┤
│      Client       │        Docker Daemon    │    Registry   │
│  (docker命令行)   │  (dockerd, containerd)  │  (Docker Hub) │
└─────────┬─────────┴─────────────────┬───────┴───────┬───────┘│                           │               │▼                           ▼               ▼
┌─────────────────┐        ┌──────────────────┐ ┌──────────────┐
│    Docker CLI   │        │ Container Runtime│ │  Image Store │
└─────────────────┘        └──────────────────┘ └──────────────┘
  • Docker CLI:命令行界面,用于向Docker守護進程發送命令
  • Docker Daemon:Docker守護進程,負責管理鏡像、容器、網絡和卷等
  • Container Runtime:容器運行時(如containerd),負責運行容器
  • Registry:鏡像倉庫,用于存儲和分發Docker鏡像

1.3 Docker vs 虛擬機

特性Docker容器虛擬機
架構直接運行在宿主機操作系統上運行在Hypervisor上
資源占用輕量級(MB級別)重量級(GB級別)
啟動速度秒級分鐘級
隔離性進程級隔離完整操作系統隔離
性能幾乎無損耗有性能損耗

關鍵區別

┌───────────────────┐      ┌───────────────────┐
│     虛擬機        │      │     Docker        │
├─────────┬─────────┤      ├─────────┬─────────┤
│ Guest OS│  應用   │      │  應用   │  依賴   │
├─────────┼─────────┤      ├─────────┼─────────┤
│ Hypervisor        │      │ Docker  │         │
├─────────┼─────────┤      ├─────────┼─────────┤
│ Host OS │         │      │ Host OS │         │
└─────────┴─────────┘      └─────────┴─────────┘

1.4 Docker核心概念

鏡像(Image)
  • Docker的"藍圖"或"模板"
  • 包含運行應用程序所需的一切
  • 只讀層,不可修改
容器(Container)
  • 鏡像的運行實例
  • 鏡像 + 可寫層
  • 應用程序實際運行的地方
倉庫(Repository)
  • 存儲Docker鏡像的地方
  • 最常用的公共倉庫:Docker Hub

Docker Hub上最受歡迎的鏡像:

  • 數據庫
    • PostgreSQL(1B+ pulls,14502 stars)
    • MySQL(1B+ pulls,15899 stars)
    • MongoDB(1B+ pulls,10623 stars)
  • 開發環境
    • Node.js(1B+ pulls,13983 stars)
    • OpenJDK(1B+ pulls,4067 stars)
    • Golang(1B+ pulls,5063 stars)
    • PHP(1B+ pulls,7790 stars)
Dockerfile
  • 創建Docker鏡像的"配方"
  • 包含一系列指令

💡 避坑指南:鏡像是靜態的,容器是動態的。你可以從同一個鏡像啟動多個容器實例。

1.5 Docker Engine更新渠道

Docker Engine提供兩種更新渠道:

  • Stable(穩定版):經過充分測試的正式發布版本
  • Test(測試版):預發布版本,用于測試新功能

生產環境建議使用Stable渠道,開發環境可考慮使用Test渠道體驗新功能。


第二章:安裝Docker

2.1 Windows系統安裝

  1. 下載Docker Desktop

    • 訪問 Docker官網
    • 點擊"Download for Windows"
  2. 安裝過程

    • 雙擊下載的安裝文件
    • 按照向導提示進行安裝
    • 建議勾選"Install required Windows components for WSL 2"
  3. 啟動Docker

    • 安裝完成后,Docker會自動啟動
    • 檢查系統托盤,看到鯨魚圖標表示Docker正在運行
  4. 驗證安裝

    在命令提示符或PowerShell中輸入:

    > docker --version
    Docker version 24.0.7, build afdd53b
    

💡 小貼士:Windows 10家庭版需要額外安裝WSL 2(Windows Subsystem for Linux 2)。安裝后可能需要重啟電腦。

許可說明:Docker Desktop 對于個人用戶、教育機構和中小型企業是免費的。大型企業(超過250名員工或年收入超過1000萬美元)需要購買商業許可。

2.2 macOS系統安裝

  1. 下載Docker Desktop

    • 訪問 Docker官網
    • 點擊"Download for Mac"
  2. 安裝過程

    • 雙擊下載的.dmg文件
    • 將Docker圖標拖到Applications文件夾
    • 在Applications中雙擊Docker.app啟動
  3. 驗證安裝

    在終端中輸入:

    > docker --version
    Docker version 24.0.7, build afdd53b
    

2.3 Linux系統安裝(Ubuntu 22.04示例)

# 1. 更新軟件包索引
> sudo apt update# 2. 安裝必要的軟件包
> sudo apt install apt-transport-https ca-certificates curl software-properties-common# 3. 添加Docker官方GPG密鑰
> curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg# 4. 設置Docker穩定版倉庫
> echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null# 5. 安裝Docker引擎
> sudo apt update
> sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin# 6. 驗證Docker是否正確安裝
> sudo docker run hello-world

💡 避坑指南:安裝后,普通用戶無法直接運行Docker命令。解決方法:

> sudo usermod -aG docker $USER
> newgrp docker  # 或者重啟終端

注意:以上以Ubuntu為例,其他Linux發行版的安裝命令請參考Docker官方安裝文檔。

2.4 Docker Desktop功能詳解

Docker Desktop不僅包含Docker Engine,還提供了一系列增強功能:

  • Docker Engine:強大的容器運行時,提供高性能和可靠的容器化應用支持
  • Docker CLI:靈活的命令行界面,提供精確的容器控制
  • Docker Compose:簡化多容器應用的管理
  • Docker Build:簡化容器鏡像構建過程
  • Docker Kubernetes:內置Kubernetes支持,無需外部集群即可本地開發
  • Volume Management:有效的數據管理解決方案
  • Synchronized File Shares:實時同步主機和容器間的文件
  • Docker Debug:高級故障排除工具
  • Hardened Docker Desktop:增強的容器隔離和安全性
  • VDI Support:虛擬桌面基礎設施集成
  • Docker Private Extensions Marketplace:定制化擴展功能

2.5 驗證安裝

無論哪個平臺,安裝完成后運行以下命令:

> docker run hello-world

如果看到類似以下輸出,說明Docker安裝成功:

Hello from Docker!
This message shows that your installation appears to be working correctly.

💡 小貼士docker --version 只驗證了客戶端。docker run hello-world 驗證整個Docker引擎(客戶端+守護進程)都已正確安裝并運行。


第三章:Docker基礎操作

3.1 第一個Docker容器

讓我們運行一個簡單的Nginx Web服務器:

> docker run -d -p 8080:80 --name my-nginx nginx

參數解釋

  • -d:后臺運行容器(detached模式)
  • -p 8080:80:將宿主機的8080端口映射到容器的80端口
  • --name my-nginx:給容器命名
  • nginx:要使用的鏡像名稱(如果本地不存在,Docker會自動從Docker Hub拉取官方nginx鏡像)

💡 小貼士docker run 命令實際上融合了 docker pull(如果鏡像不存在)、docker createdocker start 三個步驟。

驗證

  1. 打開瀏覽器
  2. 訪問 http://localhost:8080
  3. 應該看到Nginx歡迎頁面

3.2 常用Docker命令

容器管理
# 列出正在運行的容器
> docker ps# 列出所有容器(包括停止的)
> docker ps -a# 停止一個容器
> docker stop my-nginx# 啟動一個已停止的容器
> docker start my-nginx# 重啟容器
> docker restart my-nginx# 刪除容器
> docker rm my-nginx# 查看容器日志
> docker logs my-nginx# 進入正在運行的容器
> docker exec -it my-nginx bash# 查看Docker磁盤使用情況
> docker system df
鏡像管理
# 列出本地鏡像
> docker images# 拉取鏡像(從Docker Hub)
> docker pull ubuntu:22.04# 刪除鏡像
> docker rmi nginx# 構建鏡像(基于Dockerfile)
> docker build -t my-app:1.0 .

💡 避坑指南:刪除正在運行的容器前,需要先停止它:docker stop container_id && docker rm container_id,或者直接使用docker rm -f container_id強制刪除。

3.3 實戰練習:運行Python應用

  1. 創建一個簡單的Python應用:

    > mkdir python-app
    > cd python-app
    > echo "from http.server import HTTPServer, BaseHTTPRequestHandlerclass SimpleHandler(BaseHTTPRequestHandler):def do_GET(self):self.send_response(200)self.send_header('Content-type', 'text/html')self.end_headers()self.wfile.write(b'Hello from Docker!')if __name__ == '__main__':server = HTTPServer(('0.0.0.0', 8000), SimpleHandler)server.serve_forever()" > app.py
    
  2. 運行Python應用容器:

    > docker run -d -p 8000:8000 -v $(pwd):/app -w /app python:3.11 python app.py
    
  3. 訪問 http://localhost:8000 查看結果

命令解釋

  • -v $(pwd):/app:將當前目錄掛載到容器的/app目錄
  • -w /app:設置工作目錄為/app
  • python:3.11:使用Python 3.11官方鏡像

💡 小貼士:在Windows PowerShell中,$(pwd)應替換為${PWD}

📝 本章練習

  1. 運行一個Ubuntu容器:docker run -it ubuntu bash
  2. 在容器內執行ls /,查看文件系統
  3. 退出容器(輸入exit或按Ctrl+D)
  4. 再次運行相同的命令,觀察結果有何不同
  5. (挑戰)運行一個MySQL容器,使用-e MYSQL_ROOT_PASSWORD=my-secret-pw設置root密碼,并使用docker exec命令進入容器驗證MySQL是否正常運行

第四章:Dockerfile詳解

4.1 什么是Dockerfile?

Dockerfile是一個文本文件,包含了一系列指令,告訴Docker如何構建一個鏡像。

4.2 基本Dockerfile結構

讓我們創建一個簡單的Node.js應用Dockerfile:

# 1. 基礎鏡像
FROM node:18# 2. 設置工作目錄
WORKDIR /app# 3. 復制package.json(先單獨復制,利用Docker緩存)
COPY package.json .# 4. 安裝依賴
RUN npm install# 5. 復制應用代碼
COPY . .# 6. 暴露端口
EXPOSE 3000# 7. 定義啟動命令
CMD ["npm", "start"]

4.3 關鍵指令詳解

指令用途示例
FROM指定基礎鏡像FROM ubuntu:22.04
ARG定義構建參數ARG NODE_VERSION=18
FROM node:${NODE_VERSION}
RUN在鏡像中執行命令RUN apt-get update && apt-get install -y python3
COPY復制文件到鏡像COPY app.py /app/
ADD類似COPY,但支持URL和自動解壓ADD https://example.com/file.tar.gz /app/
WORKDIR設置工作目錄WORKDIR /app
ENV設置環境變量ENV NODE_ENV=production
EXPOSE聲明容器運行時監聽的端口EXPOSE 80
CMD容器啟動時執行的命令CMD ["python", "app.py"]
ENTRYPOINT容器啟動時執行的命令(不可覆蓋)ENTRYPOINT ["java", "-jar", "/app.jar"]

4.4 構建和運行自定義鏡像

  1. 創建Node.js應用:

    > mkdir node-app
    > cd node-app
    > npm init -y
    > echo 'const express = require("express");
    const app = express();
    app.get("/", (req, res) => res.send("Hello from Docker!"));
    app.listen(3000, () => console.log("Server running on port 3000"));' > index.js
    
  2. 創建Dockerfile(內容如上所述)

  3. 構建鏡像:

    > docker build -t my-node-app:1.0 .
    
  4. 運行容器:

    > docker run -d -p 3000:3000 --name node-app my-node-app:1.0
    
  5. 訪問 http://localhost:3000

💡 避坑指南:Docker構建時,默認使用當前目錄作為上下文。確保Dockerfile在項目根目錄,且不包含不必要的大文件(使用.dockerignore)。

4.5 Docker BuildKit詳解

Docker BuildKit是Docker 18.09+引入的下一代構建系統,提供了顯著的性能改進和新功能:

啟用BuildKit

# 臨時啟用
> DOCKER_BUILDKIT=1 docker build .# 永久啟用(修改daemon.json)
{"features": {"buildkit": true}
}

BuildKit優勢

  • 更快的構建速度:并行構建和緩存優化
  • 更好的安全性:隔離的構建環境
  • 高級功能
    # 語法聲明(使用BuildKit特有功能)
    # syntax=docker/dockerfile:1.3# SSH轉發
    FROM alpine
    RUN --mount=type=ssh ssh example.com ls# 構建時緩存
    RUN --mount=type=cache,target=/root/.cache/go-build go build .# 秘密管理
    RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
    

💡 小貼士:Docker 23.0+默認啟用BuildKit,可以自動清理中間層,進一步減小鏡像大小。

4.6 優化Docker鏡像大小

1. 使用合適的基鏡像
  • 優先使用alpine版本(更小)
  • 例如:node:18-alpinenode:18 小約200MB
2. 多階段構建
# 構建階段
FROM node:18 as builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production  # 使用ci確保依賴版本確定性
COPY . .
RUN npm run build# 運行階段
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package.json .
RUN npm ci --only=production
EXPOSE 3000
CMD ["node", "dist/index.js"]
3. 減少鏡像層數
# 不推薦
RUN apt-get update
RUN apt-get install -y package1 package2# 推薦(合并為一條命令)
RUN apt-get update && apt-get install -y \package1 \package2 \&& rm -rf /var/lib/apt/lists/*
4. 清理不必要的文件
RUN npm install && npm cache clean --force
5. 使用.dockerignore文件

創建.dockerignore文件,排除不需要的文件:

node_modules
.git
*.log
.env
Dockerfile
.dockerignore

📝 本章練習

  1. 為你的Python應用創建Dockerfile
  2. 構建并運行鏡像
  3. 使用docker image inspect查看鏡像詳情
  4. (挑戰)嘗試使用多階段構建優化你的Docker鏡像

第五章:Docker Compose

5.1 什么是Docker Compose?

Docker Compose是用于定義和運行多容器Docker應用程序的工具。通過一個YAML文件配置應用程序服務,然后使用一個命令創建并啟動所有服務。

5.2 安裝Docker Compose

  • Windows/macOS:Docker Desktop已包含Compose
  • Linux:Docker 20.10+已內置Compose插件,無需單獨安裝

💡 小貼士:在Linux上,舊版Docker需要單獨安裝Compose:

> sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
> sudo chmod +x /usr/local/bin/docker-compose

5.3 Docker Compose Specification

Docker Compose已發展為Compose Specification,這是云原生計算基金會(CNCF)的項目,旨在標準化多容器應用的定義。最新版本已移除version字段要求:

services:web:image: nginxports:- "8080:80"db:image: postgresenvironment:POSTGRES_PASSWORD: example

這種格式與Docker Compose、Podman Compose和Kubernetes的Kompose兼容,提供更廣泛的互操作性。

5.4 docker-compose.yml結構

version: '3.8'  # 指定Compose文件格式版本services:  # 定義所有服務web:  # 服務名稱image: nginx:latest  # 使用的鏡像ports:- "8080:80"  # 端口映射volumes:- ./html:/usr/share/nginx/html  # 卷掛載db:image: mysql:8.0environment:MYSQL_ROOT_PASSWORD: example  # 設置環境變量MYSQL_DATABASE: mydbvolumes:- db_data:/var/lib/mysql  # 命名卷volumes:  # 定義卷db_data:

💡 小貼士:對于新項目,可以直接使用Compose Specification(即直接寫 services:),這代表最新標準。工具會自動兼容。

5.5 實戰:部署WordPress應用

  1. 創建項目目錄:

    > mkdir wordpress-app
    > cd wordpress-app
    
  2. 創建docker-compose.yml文件:

    version: '3.8'services:db:image: mysql:8.0volumes:- db_data:/var/lib/mysqlrestart: alwaysenvironment:MYSQL_ROOT_PASSWORD: somewordpressMYSQL_DATABASE: wordpressMYSQL_USER: wordpressMYSQL_PASSWORD: wordpresshealthcheck:  # 添加健康檢查test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u$$MYSQL_USER", "-p$$MYSQL_PASSWORD"]interval: 10stimeout: 5sretries: 5wordpress:depends_on:db:condition: service_healthy  # 確保數據庫真正就緒image: wordpress:latestports:- "8000:80"restart: alwaysenvironment:WORDPRESS_DB_HOST: db:3306WORDPRESS_DB_USER: wordpressWORDPRESS_DB_PASSWORD: wordpressWORDPRESS_DB_NAME: wordpress
    volumes:db_data:
    
  3. 啟動應用:

    > docker-compose up -d
    
  4. 訪問 http://localhost:8000 開始WordPress安裝

  5. 常用Compose命令:

    # 啟動所有服務
    > docker-compose up -d# 停止所有服務
    > docker-compose down# 查看服務日志
    > docker-compose logs -f# 重啟服務
    > docker-compose restart wordpress# 構建/重新構建服務
    > docker-compose build
    

?? 重要提示depends_on只控制啟動順序,不等待服務真正就緒。對于需要等待數據庫初始化的應用,必須實現健康檢查并使用condition: service_healthy,這是生產環境的最佳實踐。

📝 本章練習

  1. 創建一個包含Nginx和Alpine的Compose文件
  2. 配置Nginx服務監聽8080端口
  3. 使用docker-compose up啟動服務
  4. 訪問 http://localhost:8080 驗證
  5. (挑戰)為Nginx配置自定義HTML內容(使用卷掛載)

第六章:Docker網絡

6.1 Docker網絡模式

模式描述使用場景
bridge默認模式,容器通過虛擬網橋連接單機上多個容器通信
host容器直接使用宿主機網絡需要高性能網絡的應用
none容器沒有網絡完全隔離的容器
overlay跨多個Docker守護進程的網絡Docker Swarm集群

6.2 創建自定義網絡

# 創建自定義橋接網絡
> docker network create my-network# 在自定義網絡中運行容器
> docker run -d --name web --network my-network nginx
> docker run -it --name alpine --network my-network alpine sh# 在alpine容器中測試與web容器的連接
/ # ping web

6.3 容器間通信

場景:前端應用需要連接后端API

  1. 創建自定義網絡:

    > docker network create app-network
    
  2. 啟動后端服務:

    > docker run -d --name backend --network app-network -p 5000:5000 my-backend-image
    
  3. 啟動前端服務:

    > docker run -d --name frontend --network app-network -p 3000:3000 \-e API_URL=http://backend:5000 my-frontend-image
    
  4. 前端容器可以通過http://backend:5000訪問后端服務

6.4 網絡排查

# 查看所有網絡
> docker network ls# 查看特定網絡的詳細信息
> docker network inspect app-network# 查看容器的網絡配置
> docker inspect frontend | grep IPAddress

💡 避坑指南:Docker容器使用服務名稱作為主機名進行通信。確保在代碼中使用服務名稱(如http://backend:5000)而不是IP地址。

📝 本章練習

  1. 創建一個自定義網絡test-net
  2. 在該網絡中運行兩個Nginx容器
  3. 從一個容器ping另一個容器
  4. 嘗試不使用自定義網絡,直接通過容器名通信(會失敗)
  5. (挑戰)創建一個包含前端、后端和數據庫的Compose文件,并配置正確的網絡

第七章:數據持久化

7.1 為什么需要數據持久化?

默認情況下,容器停止后,容器內的所有數據都會丟失。對于數據庫等需要持久存儲的應用,我們需要將數據存儲在容器外部。

7.2 三種數據管理方式

類型描述適用場景
數據卷(Volumes)由Docker管理的存儲區域生產環境,最佳實踐
綁定掛載(Bind Mounts)將宿主機目錄直接掛載到容器開發環境,需要實時編輯文件
tmpfs掛載僅存儲在內存中臨時數據,敏感數據

7.3 使用數據卷

# 創建命名卷
> docker volume create my-volume# 查看所有卷
> docker volume ls# 使用卷運行容器
> docker run -d -v my-volume:/app/data --name my-container nginx# 查看卷詳情
> docker volume inspect my-volume# 清理未使用的卷
> docker volume prune

7.4 數據卷備份與恢復

數據卷備份

# 創建備份容器
> docker run --rm -v my-volume:/volume -v $(pwd):/backup alpine \tar cvf /backup/backup.tar -C /volume . 

數據卷恢復

# 創建新卷
> docker volume create restore-volume# 恢復數據
> docker run --rm -v restore-volume:/volume -v $(pwd):/backup alpine \tar xvf /backup/backup.tar -C /volume

生產環境建議

  • 使用定時任務定期備份關鍵數據卷
  • 將備份存儲到安全位置(如云存儲)
  • 測試恢復流程,確保備份有效
  • 考慮使用專業備份工具如Velero(Kubernetes環境)

7.5 實戰:MySQL數據持久化

# 創建數據卷
> docker volume create mysql-data# 運行MySQL容器
> docker run -d \-v mysql-data:/var/lib/mysql \-e MYSQL_ROOT_PASSWORD=my-secret-pw \--name mysql \mysql:8.0

即使容器被刪除,數據仍然保留在mysql-data卷中。

💡 避坑指南:數據卷的路徑在宿主機上通常是/var/lib/docker/volumes/,但不應直接操作這些文件,應通過Docker命令管理。

7.6 使用綁定掛載進行開發

# 將當前目錄掛載到容器的/app目錄
> docker run -d \-v $(pwd):/app \-w /app \node:18 \npm start

開發優勢

  • 代碼修改后無需重新構建鏡像
  • 實時看到更改效果
  • 適合前端開發和熱重載

📝 本章練習

  1. 創建一個數據卷app-data
  2. 運行一個Nginx容器,將/usr/share/nginx/html掛載到該卷
  3. 在卷中創建一個index.html文件
  4. 訪問Nginx服務,驗證內容
  5. (挑戰)使用綁定掛載開發一個簡單的Node.js應用,實現代碼熱重載

第八章:實戰項目 - 部署一個完整的Web應用

8.1 項目結構

my-app/
├── frontend/       # 前端代碼(React)
├── backend/        # 吘端代碼(Node.js)
├── docker-compose.yml
└── README.md

8.2 前端Dockerfile

# frontend/Dockerfile
# 構建階段
FROM node:18 as build
WORKDIR /app
COPY package*.json ./
RUN npm ci  # 使用ci確保依賴版本確定性
COPY . .
RUN npm run build# 生產階段
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

8.3 后端Dockerfile

# backend/Dockerfile
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production  # 生產環境只安裝生產依賴
COPY . .
EXPOSE 5000
CMD ["node", "server.js"]

8.4 docker-compose.yml

version: '3.8'services:frontend:build: context: ./frontendlabels:- "org.opencontainers.image.revision=${GIT_COMMIT:-latest}"  # 注入git commit信息ports:- "3000:80"depends_on:backend:condition: service_healthynetworks:- app-networkbackend:build: context: ./backendlabels:- "org.opencontainers.image.revision=${GIT_COMMIT:-latest}"ports:- "5000:5000"environment:DB_HOST: dbDB_USER: userDB_PASS: passworddepends_on:db:condition: service_healthynetworks:- app-networkhealthcheck:test: ["CMD", "curl", "-f", "http://localhost:5000/health"]interval: 30stimeout: 10sretries: 3db:image: postgres:15environment:POSTGRES_USER: userPOSTGRES_PASSWORD: passwordPOSTGRES_DB: mydbvolumes:- pgdata:/var/lib/postgresql/datanetworks:- app-networkhealthcheck:test: ["CMD-SHELL", "pg_isready -U user"]interval: 10stimeout: 5sretries: 5networks:app-network:driver: bridgevolumes:pgdata:

💡 小貼士condition: service_healthy確保服務真正就緒后再啟動依賴服務,避免啟動順序問題。通過labels注入git commit信息便于鏡像追蹤。

8.5 部署步驟

  1. 克隆項目:

    > git clone https://github.com/yourusername/my-app.git
    > cd my-app
    
  2. 啟動應用:

    > docker-compose up -d --build
    
  3. 訪問應用:

    • 前端:http://localhost:3000
    • 后端API:http://localhost:5000/api
  4. 查看日志:

    > docker-compose logs -f
    
  5. 停止應用:

    > docker-compose down
    

📝 本章練習

  1. 創建一個簡單的前后端分離應用
  2. 為前后端分別編寫Dockerfile
  3. 創建docker-compose.yml文件,配置服務依賴和網絡
  4. 實現健康檢查,確保服務正確啟動
  5. (挑戰)添加Redis服務,并配置前后端使用Redis

第九章:常見問題與解決方案

9.1 容器無法啟動

問題:容器啟動后立即退出
原因:主進程執行完畢退出
解決方案

  • 確保CMDENTRYPOINT指定的是長期運行的進程
  • 使用-it參數運行容器進行調試:
    > docker run -it --rm my-image sh
    

💡 避坑指南:容器必須有一個前臺進程才能保持運行。如果運行的是后臺服務,需要使用-d參數或確保命令保持前臺運行。

9.2 端口沖突

問題

Error response from daemon: driver failed programming external connectivity on endpoint...: 
bind: address already in use.

解決方案

  • 更換宿主機端口:
    > docker run -p 8081:80 nginx
    
  • 停止占用端口的進程:
    # Linux/Mac
    > lsof -i :8080# Windows
    > netstat -ano | findstr :8080
    

9.3 鏡像拉取失敗

問題

Error response from daemon: Get https://registry-1.docker.io/v2/: 
net/http: request canceled while waiting for connection

解決方案

  • 檢查網絡連接
  • 配置Docker鏡像加速器(針對中國用戶):
    1. 創建或修改 /etc/docker/daemon.json
    2. 添加:
      {"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn","https://hub-mirror.c.163.com"]
      }
      
    3. 重啟Docker:sudo systemctl restart docker

💡 小貼士:Docker Desktop用戶可以在設置中直接配置鏡像加速器。常用的鏡像加速器包括:

  • 阿里云容器鏡像服務(需登錄獲取個人加速地址)
  • 網易云:https://hub-mirror.c.163.com
  • 中國科學技術大學:https://docker.mirrors.ustc.edu.cn

9.4 容器內無法訪問網絡

問題:容器內無法ping通外部網絡
解決方案

  • 檢查DNS配置:
    > docker run --dns=8.8.8.8 -it ubuntu ping google.com
    
  • 檢查防火墻設置
  • 重置Docker網絡:
    > docker network prune
    

9.5 清理磁盤空間

問題:Docker占用大量磁盤空間
解決方案

# 清理停止的容器
> docker container prune# 清理未使用的鏡像
> docker image prune# 清理未使用的網絡
> docker network prune# 清理所有未使用的資源(包括構建緩存)
> docker system prune -a# 查看磁盤使用情況
> docker system df

💡 避坑指南:定期清理可以避免磁盤空間不足問題。建議在CI/CD管道中添加清理步驟。

📝 本章練習

  1. 故意制造一個端口沖突,然后解決它
  2. 模擬鏡像拉取失敗,配置鏡像加速器
  3. 創建一個無法啟動的容器,使用-it調試
  4. (挑戰)編寫一個腳本,每天自動清理Docker資源

第十章:最佳實踐與安全建議

10.1 鏡像構建最佳實踐

  1. 使用.dockerignore文件

    node_modules
    .git
    *.log
    .env
    Dockerfile
    .dockerignore
    
  2. 合理排序Dockerfile指令

    • 將變化較少的指令放在前面
    • 例如:先COPY package.json,再RUN npm install,最后COPY其他文件
  3. 使用多階段構建

    • 減小最終鏡像大小
    • 避免將構建工具包含在生產鏡像中
  4. 指定軟件包版本

    RUN apt-get install -y python3=3.10.6-1ubuntu0.1
    
  5. 鏡像分層原理

    • Docker鏡像由多層只讀層組成
    • 每條Dockerfile指令創建一個新層
    • 利用緩存機制:當某一層發生變化時,其后的所有層都需要重新構建
    • 合并相關操作到同一層可減少鏡像層數

10.2 安全最佳實踐

  1. 不要以root用戶運行容器

    FROM node:18
    RUN groupadd -r appuser && useradd -r -g appuser appuser
    USER appuser
    
  2. 定期更新基礎鏡像

    > docker pull node:18
    > docker build -t my-app:latest .
    
  3. 掃描鏡像漏洞

    # 需要先登錄Docker Hub
    > docker login
    > docker scan my-app:latest# 或者使用開源工具如Trivy
    > trivy image --severity CRITICAL,HIGH my-app:latest
    
  4. 限制容器資源

    > docker run -d \--memory=512m \--cpus=1.5 \my-app
    
  5. 不要在鏡像中存儲敏感信息

    • 使用環境變量或Docker secrets
    • 通過docker run -edocker-compose的environment設置
  6. 使用非最新版本的具體標簽

    • 使用node:18.18.0-alpine 而不是 node:18-alpinenode:latest
    • 確保部署的確定性和安全性
  7. 最小權限原則

    > docker run --cap-drop ALL --cap-add NET_BIND_SERVICE my-app
    
  8. Docker內容信任(Docker Content Trust)

    # 啟用內容信任
    > export DOCKER_CONTENT_TRUST=1# 簽名并推送鏡像
    > docker trust sign myimage:tag# 驗證簽名
    > docker trust inspect myimage:tag
    
  9. 安全上下文配置

    services:app:# ...security_opt:- no-new-privileges:trueread_only: truecap_drop:- ALLcap_add:- NET_BIND_SERVICE
    

10.3 生產環境部署建議

  1. 使用編排工具

    • Docker Swarm(內置)
    • Kubernetes(更強大,適合大型部署)
  2. 實現健康檢查

    HEALTHCHECK --interval=30s --timeout=3s \CMD curl -f http://localhost/ || exit 1
    
  3. 集中式日志管理

    • 使用ELK棧(Elasticsearch, Logstash, Kibana)
    • 或Docker日志驅動:docker run --log-driver=json-file ...
  4. 監控與告警

    • Prometheus + Grafana
    • cAdvisor(容器資源監控)
  5. Docker Desktop的Kubernetes集成
    Docker Desktop內置了Kubernetes支持,無需額外安裝即可在本地開發環境中使用Kubernetes:

    1. 啟用Kubernetes

      • Windows/macOS:Docker Desktop設置 → Kubernetes → 勾選"Enable Kubernetes"
      • Linux:需單獨安裝
    2. 驗證安裝

      > kubectl cluster-info
      Kubernetes control plane is running at https://kubernetes.docker.internal:6443
      
    3. 使用Kubernetes

      > kubectl create deployment nginx --image=nginx
      > kubectl expose deployment nginx --port=80
      > kubectl get pods
      

    Docker Desktop的Kubernetes支持包括:

    • 單節點集群(開發使用)
    • 與Docker Compose的集成
    • 簡單的UI管理
    • 本地開發的理想環境

💡 避坑指南:生產環境應避免使用latest標簽,而應使用具體的版本號,確保可重復部署。

📝 本章練習

  1. 為你的應用Dockerfile添加非root用戶
  2. 添加健康檢查指令
  3. 限制容器的內存和CPU使用
  4. (挑戰)使用Docker掃描工具檢查你的鏡像漏洞

第十一章:進階主題

11.1 Docker Swarm簡介

Docker Swarm是Docker原生的集群管理和編排工具。

基本概念

  • Node:集群中的Docker主機
  • Manager:管理集群的節點
  • Worker:執行任務的節點
  • Service:在集群中運行的應用

創建Swarm集群

# 初始化Swarm(作為Manager)
> docker swarm init# 獲取加入令牌
> docker swarm join-token worker# 在其他節點上加入Swarm
> docker swarm join --token <token> <manager-ip>:2377

部署服務

> docker service create --replicas 3 -p 80:80 --name my-web nginx

11.2 Kubernetes簡介

Kubernetes(簡稱K8s)是一個開源的容器編排系統,用于自動化部署、擴展和管理容器化應用。

核心概念

  • Pod:Kubernetes中最小的部署單元,可包含一個或多個容器
  • Deployment:管理Pod的聲明式更新
  • Service:定義Pod的訪問策略
  • Namespace:資源的虛擬集群

簡單示例

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deployment
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.14.2ports:- containerPort: 80

應用配置:

> kubectl apply -f deployment.yaml

11.3 CI/CD集成

GitHub Actions示例

name: Docker Image CIon:push:branches: [ main ]jobs:build:runs-on: ubuntu-lateststeps:- uses: actions/checkout@v4with:fetch-depth: 0  # 獲取所有歷史記錄,便于生成標簽- name: Set up Docker Buildxuses: docker/setup-buildx-action@v3- name: Login to DockerHubuses: docker/login-action@v2with:username: ${{ secrets.DOCKERHUB_USERNAME }}password: ${{ secrets.DOCKERHUB_TOKEN }}- name: Extract metadata for Dockerid: metauses: docker/metadata-action@v5with:images: user/apptags: |type=shatype=ref,event=branchtype=ref,event=prtype=semver,pattern={{version}}type=semver,pattern={{major}}.{{minor}}- name: Build and pushuses: docker/build-push-action@v5with:context: .push: truetags: ${{ steps.meta.outputs.tags }}labels: ${{ steps.meta.outputs.labels }}cache-from: type=ghacache-to: type=gha,mode=max

💡 小貼士:Docker 23.0+引入了Buildx Build Cache,可以顯著加速CI/CD中的鏡像構建過程。使用GitHub Actions的緩存功能可以進一步提升構建效率。

11.4 Docker Swarm和Kubernetes對比

特性Docker SwarmKubernetes
學習曲線簡單,易于上手陡峭,需要更多學習
安裝配置簡單,Docker內置復雜,需要單獨安裝
功能豐富度基礎功能非常豐富,功能全面
社區支持中等非常活躍
適用場景中小型應用,簡單部署大型應用,復雜部署
擴展性有限非常強大
自動伸縮基礎支持高級支持
滾動更新支持高級支持
健康檢查基礎支持高級支持
網絡策略基礎支持高級支持

選擇建議

  • 如果是小型團隊或簡單應用,Docker Swarm足夠使用
  • 如果需要高級功能或大規模部署,Kubernetes是更好的選擇
  • 對于本地開發,Docker Desktop內置的Kubernetes支持是理想選擇

📝 本章練習

  1. 初始化一個Docker Swarm集群
  2. 部署一個簡單的服務
  3. 擴展服務的副本數
  4. (挑戰)嘗試將你的應用部署到Kubernetes集群

附錄A:Docker命令速查表

基礎命令

命令描述
docker ps列出正在運行的容器
docker ps -a列出所有容器
docker images列出本地鏡像
docker run [OPTIONS] IMAGE [COMMAND]運行容器
docker stop CONTAINER停止容器
docker start CONTAINER啟動容器
docker rm CONTAINER刪除容器
docker rmi IMAGE刪除鏡像
docker logs CONTAINER查看容器日志
docker exec -it CONTAINER COMMAND在運行的容器中執行命令

高級命令

命令描述
docker build -t TAG .構建鏡像
docker-compose up啟動Compose服務
docker network ls列出網絡
docker volume ls列出數據卷
docker system df查看Docker磁盤使用
docker system prune清理未使用的資源
docker inspect CONTAINER查看容器詳細信息
docker stats實時資源使用情況
docker events監聽Docker事件
docker diff CONTAINER查看容器文件系統變化

附錄B:推薦學習資源

📚 官方文檔

  • Docker官方文檔
  • Docker Hub
  • Compose Specification

📺 視頻教程

  • Docker入門教程(B站)
  • Docker & Kubernetes: The Practical Guide (Udemy)

💻 實踐平臺

  • Play with Docker
  • Katacoda Docker場景

📖 書籍推薦

  • 《Docker技術入門與實戰》
  • 《Kubernetes權威指南》

🔧 實用工具

  • Trivy - 容器漏洞掃描工具
  • Dive - 鏡像層分析工具
  • Lens - Kubernetes IDE
  • Portainer - Docker管理UI

結語:繼續你的Docker之旅

恭喜你完成了Docker入門學習!現在你已經掌握了Docker的核心概念和實用技能,可以開始在自己的項目中應用Docker了。

下一步建議

  1. 實踐項目:嘗試將你現有的一個應用容器化
  2. 深入學習
    • 閱讀Docker官方文檔
    • 學習Kubernetes基礎知識
  3. 加入社區
    • Docker官方論壇
    • Stack Overflow的docker標簽
    • 本地Docker/Kubernetes用戶組

記住,最好的學習方式是動手實踐!從簡單開始,逐步增加復雜度,很快你就會成為Docker高手。

祝你在容器化旅程中一切順利! 🐳


📝 附:學習進度檢查表

? 已完成? 未完成📅 計劃完成日期
安裝Docker
運行第一個容器
理解Dockerfile
使用Docker Compose
配置Docker網絡
實現數據持久化
部署完整Web應用
解決常見問題
應用最佳實踐
探索進階主題

填寫你的學習計劃,跟蹤進度!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/921563.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/921563.shtml
英文地址,請注明出處:http://en.pswp.cn/news/921563.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HOT100--Day15--98. 驗證二叉搜索樹,230. 二叉搜索樹中第 K 小的元素,199. 二叉樹的右視圖

HOT100–Day15–98. 驗證二叉搜索樹&#xff0c;230. 二叉搜索樹中第 K 小的元素&#xff0c;199. 二叉樹的右視圖 每日刷題系列。今天的題目是《力扣HOT100》題單。 題目類型&#xff1a;二叉樹。 關鍵&#xff1a;要深刻理解《遞歸》 98. 驗證二叉搜索樹 思路&#xff1a; …

獨角數卡對接藍鯨支付平臺實現個人

目錄 什么是獨角數卡&#xff1f;安裝部署教程一、獨角數卡安裝二、獨角數卡支付配置三、獨角數卡BUG修復 什么是獨角數卡&#xff1f; ? ? ? ? ? ? ? 獨角數卡(Dujiaoka)?是一款基于Laravel框架開發的開源式站長自動化售貨解決方案&#xff0c;主要用于虛擬商品和數字…

人工智能常見分類

人工智能的分類方式多樣&#xff0c;以下是一些常見的分類方法及具體類型&#xff1a; 一、按功能目標分類 弱人工智能&#xff08;ANI&#xff0c;Narrow AI&#xff09;&#xff1a;專注于單一任務&#xff0c;無自主意識&#xff0c;如圖像識別&#xff08;人臉解鎖&#xf…

PO BAPI bapi_po_create1

當執行BAPI時,需要導入增強字段,其中增強字段包含數值型號字段時,需要增強BADI::ME_BAPI_PO_CUST 代碼如下: 記錄一下,下次自己繼續用 bapi處: ls_te_item-po_item = lv_item.ls_te_item-zz001 = 11.ls_te_item-zz005 = 22.ls_te_item-zz008 = 33.ls_te_item-zz009 = 44…

棧欺騙技術的作用是什么?

好的&#xff0c;我們來詳細解釋一下“棧欺騙技術”&#xff08;Stack Spoofing&#xff09;的作用。簡單來說&#xff0c;棧欺騙技術的核心作用是隱藏程序&#xff08;尤其是惡意軟件或安全工具&#xff09;的真實調用鏈&#xff0c;使其逃避基于棧回溯&#xff08;Stack Walk…

Nano-banana 模型對接教程:最懂創作者的 AI 模型,比GPT-4o還強!

Nano-banana 模型對接教程&#xff08;含 BaseURL&#xff09; Nano Banana 是谷歌推出的革命性 AI 圖像編輯模型&#xff0c;代表了從"AI繪畫工具"到"AI創意伙伴"的范式轉移。它不再是被動執行指令&#xff0c;而是能深刻理解已有圖像的上下文、光影、物…

CEEMDAN-PSO-CNN-GRU 鋰電池健康狀態預測matlab

代碼說明 這個實現包含以下主要組成部分: 數據準備:加載并預處理鋰電池容量數據,劃分訓練集和測試集 CEEMDAN分解:將原始信號分解為多個本征模態函數(IMF)和一個殘差項 PSO優化:使用粒子群算法優化CNN-GRU網絡的超參數 CNN-GRU模型:構建并訓練卷積神經網絡與門控循環…

MySQL 主從讀寫分離架構

我們首先來詳細、清晰地講解 MySQL 主從讀寫分離架構&#xff0c;然后逐一解答你提出的以及補充的高頻面試問題。第一部分&#xff1a;MySQL 主從讀寫分離架構詳解1. 什么是主從復制與讀寫分離&#xff1f;你可以把它想象成一個 “團隊作戰” 的模式。主數據庫 (Master)&#x…

HTML 中的 CSS 使用說明

CSS 使用說明 1. CSS 概述 CSS (Cascading Style Sheets) 是一種用于描述 HTML 或 XML&#xff08;包括如 SVG、MathML 等 XML 方言&#xff09;文檔呈現的樣式表語言。CSS 描述了元素應該如何在屏幕、紙張或其他媒體上顯示。 2. CSS 的基本語法 CSS 規則由兩個主要部分組成…

gitlab推送失敗,內存不足的處理

git提交時報錯&#xff1a; 2025-09-03 20:03:32.583 [info] > git push origin master:master [4866ms]2025-09-03 20:03:32.583 [info] fatal: Out of memory, malloc failed (tried to allocate 1048576000 bytes)看了下服務器內存&#xff0c;空余的只有幾百M了。 用hto…

【FastDDS】Discovery ( 05-Discovery Server Settings)

發現服務器設置 這種機制基于客戶端-服務器發現模式,即元流量(域參與者之間用于識別彼此的消息交換)由一個或多個服務器域參與者管理(左圖),而在簡單發現(右圖)中,元流量通過IP多播協議等消息廣播機制進行交換。有一款發現服務器工具可簡化發現服務器的設置和測試。 …

Xilinx ZYNQ 開發環境中搭建Qt環境

在 Xilinx ZYNQ 開發環境中搭建 Qt 環境,意味著你要開發運行在 ZYNQ 嵌入式 Linux 系統上的 GUI 應用程序。這比在 PC 上搭建 Qt 要復雜一些,因為它涉及交叉編譯:在你的 PC(主機)上編譯出能在 ZYNQ 芯片(目標機)的 ARM Cortex-A9 核心上運行的程序。 整個過程可以分為以…

【數學建模】用代碼搞定無人機煙幕:怎么擋導彈最久?

前言&#xff1a;歡迎各位光臨本博客&#xff0c;這里小編帶你直接手撕**&#xff0c;文章并不復雜&#xff0c;愿諸君耐其心性&#xff0c;忘卻雜塵&#xff0c;道有所長&#xff01;&#xff01;&#xff01;&#xff01; **&#x1f525;個人主頁&#xff1a;IF’Maxue-CSDN…

linux Kbuild詳解關于fixdep、Q、quiet、escsq

linux Kbuild詳解關于if_changed_rule的any-prereq和arg-check原理及info調試關于fixdep沒有展開&#xff0c;這里說下。 文章目錄1. escsq2. Q、quiet2. 1 make V(0、1、2&#xff09;2. 2 make V(0、1)來控制Q、quiet3. fixdep3. 1 fixdep是什么3. 2 fixdep為什么3.2.1 .conf…

notepad++ 正則表達式

在 Notepad 中&#xff0c;正則表達式&#xff08;Regular Expressions, Regex&#xff09; 是一個強大的搜索和替換工具&#xff0c;可以高效地處理文本。以下是 Notepad 正則表達式 的指南&#xff1a;1. 如何在 Notepad 中使用正則表達式打開搜索窗口&#xff1a;快捷鍵 Ctr…

MySQL Cluster核心優缺點

MySQL Cluster 是 MySQL 官方提供的 分布式、內存優先、高可用 的數據庫解決方案&#xff08;基于 NDB 存儲引擎&#xff09;。它采用 Share-Nothing 架構&#xff0c;數據自動分片&#xff08;Sharding&#xff09;并分布在多個節點上&#xff0c;適用于需要極高可用性和實時性…

訓練+評估流程

訓練評估流程1、要求2、訓練評估&#xff08;PyTorch TensorBoard &#xff09;完整代碼&#xff08;單文件示例&#xff09;運行方法功能對應表3、pytorch自定義評估要繼承哪個類&#xff1f;4、HF Trainer和SB35、 匯總1. PyTorch Lightning TensorBoard ModelCheckpoint …

【開題答辯全過程】以 基于Android的點餐系統為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

【音視頻】Http-FLV 介紹

一、Http-FLV 原理 HTTP-FLV 是基于 HTTP 協議的 FLV&#xff08;Flash Video&#xff09;流媒體傳輸方式。它使用 HTTP 協議而不是傳統的 RTMP 協議來傳輸 FLV 格式的視頻流。HTTP-FLV 在 Web 視頻直播場景中得到了廣泛應用&#xff0c;尤其是在不支持或不希望使用 RTMP 協議的…

uniapp vue頁面傳參到webview.nvue頁面的html或者另一vue中

在app內部使用 uni.$emit(collectiones, { data: gx });傳到webview.nvue頁面 在webview.nvue頁面接受 uni.$on(collectiones, (data) > {console.log(接收到的數據:, data.data);});使用evalJS方法 nvue webview通信示例 這塊使用receiveMessageFromNvue方法這樣傳入的 u…