
簡介這份PDF面向零基礎(chǔ)或缺乏容器化經(jīng)驗的開發(fā)者與運維人員系統(tǒng)梳理Docker從概念到實戰(zhàn)的完整入門路徑。內(nèi)容涵蓋容器與虛擬機(jī)的差異對比、Ubuntu環(huán)境下的安裝與用戶組配置、鏡像與容器生命周期管理、調(diào)試日志技巧并以部署WordPress為例演示docker-compose.yml編寫與服務(wù)啟動同時講解數(shù)據(jù)卷與綁定掛載兩種持久化方案及容器安全最佳實踐。資源包共1個PDF文件大小約760KB篇幅緊湊、結(jié)構(gòu)清晰適合作為案頭速查手冊。目前已有1057人學(xué)習(xí)說明其內(nèi)容經(jīng)過一定規(guī)模讀者驗證。讀者可借此快速搭建本地Docker環(huán)境掌握常用命令與排錯思路并通過WordPress實戰(zhàn)理解多容器編排流程為后續(xù)進(jìn)階學(xué)習(xí)打下基礎(chǔ)。1. 從一臺干凈的 Ubuntu 說起這份 Docker 入門指南到底能幫你省掉哪些彎路如果你手上有一臺剛裝好的 Ubuntu想跑個 Nginx 或者 WordPress傳統(tǒng)做法是apt install一堆依賴然后開始跟版本沖突、端口占用、配置文件路徑搏斗。這份《Docker 新手入門指南從零開始掌握容器化技術(shù)》解決的正是這個場景——它不講空泛的容器哲學(xué)而是從卸載舊版本、配軟件源、裝 Docker Engine 一路寫到用 docker-compose 起一套 WordPress中間穿插鏡像管理、容器生命周期、數(shù)據(jù)卷和綁定掛載。適合兩類人一是剛接觸容器化技術(shù)、需要一份能照著敲的實操手冊的開發(fā)者二是運維轉(zhuǎn)云原生、想把 Docker 安裝教程和 docker-compose 編排一次性跑通的從業(yè)者。它不覆蓋 Kubernetes也不深入網(wǎng)絡(luò)模式但把單機(jī)容器化最常用的 80% 操作講透了。2. 安裝與權(quán)限配置Ubuntu 上把 Docker Engine 裝干凈2.1 為什么不用 apt 自帶的 docker.ioUbuntu 官方源里的docker.io版本通常落后于 Docker 官方倉庫而且包名和依賴關(guān)系跟官方docker-ce不一致。常見做法是先把舊版本清掉再通過 Docker 官方 GPG key 和軟件源安裝。這份指南給的就是官方倉庫路線好處是后續(xù)docker compose插件、docker buildx都能一起裝上不用單獨折騰。另一個容易被忽略的點是containerd和runc的版本——官方源會一并管理避免手動裝出現(xiàn)版本錯配。2.2 安裝命令逐段拆解# 卸載可能存在的舊版本避免包沖突 sudo apt-get remove docker docker-engine docker.io containerd runc # 更新索引并安裝證書、curl、gnupg sudo apt-get update sudo apt-get install ca-certificates curl gnupg # 創(chuàng)建 keyrings 目錄權(quán)限 0755 sudo install -m 0755 -d /etc/apt/keyrings # 下載 Docker 官方 GPG key 并解碼存放 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg # 寫入軟件源arch 和 VERSION_CODENAME 自動取當(dāng)前系統(tǒng)值 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu \ $(. /etc/os-release echo $VERSION_CODENAME) stable | \ sudo tee /etc/apt/sources.list.d/docker.list /dev/null # 安裝 Docker Engine、CLI、containerd 以及 buildx、compose 插件 sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io \ docker-buildx-plugin docker-compose-plugin # 驗證拉取 hello-world 并運行 sudo docker run hello-world邏輯說明install -m 0755 -d確保 keyrings 目錄存在且權(quán)限正確否則gpg --dearmor會因目錄不存在報錯。$(dpkg --print-architecture)和$(. /etc/os-release echo $VERSION_CODENAME)是讓軟件源自動適配當(dāng)前架構(gòu)和 Ubuntu 代號避免手寫jammy或focal寫錯。最后一步docker run hello-world不只是驗證安裝它還會檢查 Docker daemon 是否在運行、能否拉取鏡像、容器能否正常啟動——三個環(huán)節(jié)一次過。參數(shù)說明docker-ce是社區(qū)版引擎docker-ce-cli是命令行客戶端containerd.io是底層容器運行時docker-buildx-plugin提供多平臺構(gòu)建能力docker-compose-plugin讓你能用docker compose而不是老式的docker-compose二進(jìn)制。2.3 把當(dāng)前用戶加入 docker 組裝完之后每次敲docker都要加sudo原因是/var/run/docker.sock默認(rèn)屬于 root。把用戶加入 docker 組就能免 sudo# 創(chuàng)建 docker 組已存在會提示忽略即可 sudo groupadd docker # 將當(dāng)前用戶加入 docker 組 sudo usermod -aG docker $USER # 刷新當(dāng)前 shell 的組信息或者直接退出重新登錄 newgrp docker # 驗證不加 sudo 運行 hello-world docker run hello-world邏輯說明usermod -aG的-a是追加不加-a會把你從其他附加組里踢出去。newgrp docker只對當(dāng)前終端生效新開的終端會自動讀取新組。如果newgrp后仍然提示權(quán)限拒絕檢查/var/run/docker.sock的屬組是不是 docker常見情況是 Docker 服務(wù)沒重啟導(dǎo)致 socket 屬組沒更新。注意把用戶加入 docker 組等同于給了該用戶 root 級權(quán)限因為容器可以掛載宿主機(jī)根目錄。生產(chǎn)環(huán)境里更穩(wěn)妥的做法是用 rootless 模式或 sudo 白名單但開發(fā)機(jī)上加組是常規(guī)操作。3. 鏡像與容器生命周期把 docker run 的參數(shù)吃透3.1 鏡像管理pull、images、rmi、build鏡像操作是日常最高頻的動作。這份指南列了四條命令但實際用起來有幾個細(xì)節(jié)值得展開# 拉取 nginx 最新版鏡像 docker pull nginx:latest # 查看本地鏡像含鏡像 ID、標(biāo)簽、大小 docker images # 刪除指定鏡像 docker rmi nginx:latest # 根據(jù)當(dāng)前目錄的 Dockerfile 構(gòu)建鏡像打標(biāo)簽 myapp:v1 docker build -t myapp:v1 .邏輯說明docker pull nginx:latest里的latest是默認(rèn)標(biāo)簽但生產(chǎn)環(huán)境不建議用latest因為每次拉取可能拿到不同版本導(dǎo)致“昨天還能跑今天掛了”的玄學(xué)問題。docker images輸出里的 IMAGE ID 是短 ID刪除時可以用短 ID 也可以用倉庫:標(biāo)簽。docker rmi如果鏡像被容器引用會報錯需要先刪容器或加-f強(qiáng)制。docker build最后的.是構(gòu)建上下文路徑不是 Dockerfile 路徑——Dockerfile 默認(rèn)在上下文根目錄用-f可以指定其他位置。參數(shù)說明-t給鏡像打標(biāo)簽格式是名稱:版本--no-cache在構(gòu)建時禁用緩存排查“改了代碼但鏡像沒變”時用--platform指定目標(biāo)架構(gòu)比如在 x86 機(jī)器上構(gòu)建 arm64 鏡像。3.2 容器生命周期run、ps、stop、start、rm容器生命周期命令看似簡單但docker run的參數(shù)組合是新手翻車最多的地方# 后臺運行 nginx把宿主機(jī) 80 映射到容器 80命名 my-nginx docker run -d -p 80:80 --name my-nginx nginx # 查看運行中的容器 docker ps # 查看所有容器包括已停止的 docker ps -a # 停止、啟動、刪除容器 docker stop my-nginx docker start my-nginx docker rm my-nginx邏輯說明-d讓容器在后臺運行不加的話終端會被前臺進(jìn)程占住。-p 80:80是宿主機(jī)端口:容器端口順序反了就連不上。--name給容器起名不起名的話 Docker 會隨機(jī)分配一個名字后續(xù)操作得先docker ps查 ID。docker stop發(fā)送 SIGTERM 并等待 10 秒超時再 SIGKILLdocker rm只能刪已停止的容器運行中的要加-f。參數(shù)說明-it組合用于交互式容器-i保持 stdin 打開-t分配偽終端--restart控制重啟策略always是開機(jī)自啟unless-stopped是除非手動停止否則自啟-e注入環(huán)境變量WordPress 案例里大量用到。3.3 調(diào)試與日志exec、logs、inspect容器出問題時這三個命令是主要排查手段# 進(jìn)入容器終端bash 不存在時換 sh docker exec -it my-nginx bash # 查看容器日志-f 持續(xù)輸出--tail 只看最后 N 行 docker logs -f --tail 100 my-nginx # 查看容器詳細(xì)信息輸出 JSON docker inspect my-nginx邏輯說明docker exec是在運行中的容器里開一個新進(jìn)程容器停了就用不了得用docker start先起來。docker logs讀的是容器主進(jìn)程的 stdout/stderr如果應(yīng)用把日志寫到文件里logs 看不到得 exec 進(jìn)去 cat。docker inspect輸出很長常用--format過濾比如docker inspect --format{{.NetworkSettings.IPAddress}} my-nginx直接拿 IP。參數(shù)說明exec的-it和run一樣logs的--since按時間過濾--timestamps加時間戳inspect的-f或--format用 Go 模板語法提取字段。提示docker exec進(jìn)去之后做的修改不會保存到鏡像容器刪除就沒了。要持久化得改 Dockerfile 重新構(gòu)建或者用數(shù)據(jù)卷掛載。4. 用 docker-compose 部署 WordPress多容器編排的第一課4.1 為什么 WordPress 適合當(dāng)?shù)谝粋€ compose 項目WordPress 需要兩個服務(wù)MySQL 數(shù)據(jù)庫和 WordPress 本身。用docker run起兩個容器再手動連網(wǎng)絡(luò)、傳環(huán)境變量也能跑但 compose 用一個 YAML 文件就把依賴關(guān)系、網(wǎng)絡(luò)、卷全聲明了。這份指南給的 compose 文件是經(jīng)典的最小可用配置適合理解services、volumes、depends_on、environment四個核心字段。4.2 docker-compose.yml 逐字段拆解version: 3 services: db: image: mysql:8.0 volumes: - db_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: wordpress MYSQL_USER: wpuser MYSQL_PASSWORD: wppass wordpress: image: wordpress:latest ports: - 8000:80 environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wpuser WORDPRESS_DB_PASSWORD: wppass depends_on: - db volumes: db_data:邏輯說明db服務(wù)用mysql:8.0鏡像volumes把命名卷db_data掛到/var/lib/mysql這樣容器刪了數(shù)據(jù)還在。environment里的四個變量是 MySQL 鏡像約定的初始化參數(shù)MYSQL_DATABASE會自動建庫MYSQL_USER和MYSQL_PASSWORD會自動建用戶并授權(quán)。wordpress服務(wù)把宿主機(jī) 8000 映射到容器 80WORDPRESS_DB_HOST寫db是因為 compose 默認(rèn)給所有服務(wù)建一個網(wǎng)絡(luò)服務(wù)名就是 DNS 名。depends_on只保證啟動順序不保證 MySQL 就緒——WordPress 啟動時如果 MySQL 還沒初始化完會報連接失敗但刷新幾次就好了。參數(shù)說明version: 3是 compose 文件格式版本新版 Docker 可以省略ports的引號建議保留避免 YAML 把8000:80解析成時間volumes頂層聲明命名卷服務(wù)里引用時寫卷名:容器路徑。4.3 啟動、驗證與常見調(diào)整# 在 docker-compose.yml 所在目錄執(zhí)行后臺啟動 docker compose up -d # 查看服務(wù)狀態(tài) docker compose ps # 查看某個服務(wù)的日志 docker compose logs -f wordpress # 停止并刪除容器、網(wǎng)絡(luò)但保留卷 docker compose down # 停止并刪除容器、網(wǎng)絡(luò)、卷 docker compose down -v邏輯說明docker compose up -d會按依賴順序創(chuàng)建網(wǎng)絡(luò)、卷、容器。docker compose ps顯示的是 compose 項目下的容器比docker ps更聚焦。docker compose down默認(rèn)不刪卷數(shù)據(jù)還在加-v才刪卷這個參數(shù)用之前想清楚刪了就找不回來。訪問http://localhost:8000就能看到 WordPress 安裝界面。如果頁面報“Error establishing a database connection”先docker compose logs db看 MySQL 是否初始化完成再docker compose logs wordpress看連接參數(shù)。常見原因是 MySQL 8.0 的認(rèn)證插件和舊版 WordPress 不兼容但wordpress:latest已經(jīng)處理了這個問題。注意compose 文件里的密碼是明文本地開發(fā)無所謂放到版本控制里之前記得改成環(huán)境變量文件.env并加入.gitignore。5. 數(shù)據(jù)持久化與安全卷、綁定掛載和非 root 運行5.1 數(shù)據(jù)卷與綁定掛載的選型Docker 的數(shù)據(jù)持久化有兩種方式命名卷和綁定掛載。命名卷由 Docker 管理存在/var/lib/docker/volumes/下適合數(shù)據(jù)庫這類不需要直接訪問文件的場景。綁定掛載把宿主機(jī)目錄直接映射進(jìn)容器適合開發(fā)時改代碼即時生效。# 命名卷創(chuàng)建 my-vol掛到容器的 /app docker volume create my-vol docker run -d \ --name devtest \ -v my-vol:/app \ nginx:latest # 綁定掛載把當(dāng)前目錄的 html 掛到 nginx 的網(wǎng)頁目錄 docker run -d \ --name devtest \ -v $(pwd)/html:/usr/share/nginx/html \ nginx:latest邏輯說明-v my-vol:/app里my-vol是卷名Docker 會自動創(chuàng)建-v $(pwd)/html:/usr/share/nginx/html里宿主機(jī)路徑必須是絕對路徑$(pwd)展開當(dāng)前目錄。綁定掛載的權(quán)限問題很常見——容器內(nèi)進(jìn)程的 UID 和宿主機(jī)文件屬主不一致時會寫不進(jìn)去解決辦法是-u指定 UID 或者調(diào)整宿主機(jī)目錄權(quán)限。參數(shù)說明docker volume ls列出所有卷docker volume inspect my-vol看卷的掛載點docker volume rm my-vol刪卷。綁定掛載加:ro可以只讀掛載比如-v $(pwd)/config:/etc/nginx/conf.d:ro。5.2 非 root 運行與最小化鏡像這份指南的安全部分給了兩條原則最小化鏡像和非 root 運行。Dockerfile 示例用node:18-alpine做基礎(chǔ)鏡像USER node切換非 root 用戶FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --onlyproduction USER node CMD [node, server.js]邏輯說明alpine鏡像體積只有幾十 MB比node:18小一個數(shù)量級但 alpine 用的是 musl libc某些依賴 glibc 的 npm 包會出問題構(gòu)建時報錯就換node:18-slim。npm ci比npm install更適合 CI 環(huán)境它嚴(yán)格按package-lock.json安裝不會改鎖文件。USER node必須在COPY和RUN之后否則后續(xù)文件屬主會變成 node可能導(dǎo)致權(quán)限問題。參數(shù)說明WORKDIR創(chuàng)建并切換目錄后續(xù)COPY和RUN都在這個目錄下COPY package*.json ./先只拷依賴清單利用 Docker 層緩存代碼改了不用重裝依賴--onlyproduction跳過 devDependencies。提示docker scan可以掃描鏡像漏洞但需要登錄 Docker Hub。替代方案是trivy image 鏡像名本地跑不需要賬號。6. 排查清單與進(jìn)階路徑那些文檔沒寫的翻車點6.1 五條血淚踩坑記錄現(xiàn)象docker run hello-world報Cannot connect to the Docker daemon。原因Docker 服務(wù)沒啟動或者當(dāng)前用戶不在 docker 組且沒加 sudo。 解決sudo systemctl start docker啟動服務(wù)sudo systemctl enable docker設(shè)開機(jī)自啟權(quán)限問題按第 2.3 節(jié)加組后重新登錄?,F(xiàn)象docker pull卡住或超時。原因默認(rèn)鏡像倉庫在國內(nèi)訪問不穩(wěn)定。 解決配置鏡像加速器編輯/etc/docker/daemon.json加registry-mirrors然后sudo systemctl restart docker。注意加速器地址會失效用之前先確認(rèn)可用性。現(xiàn)象docker compose up后 WordPress 報數(shù)據(jù)庫連接錯誤。原因MySQL 8.0 初始化需要時間WordPress 啟動太快連不上或者WORDPRESS_DB_HOST寫成了localhost而不是服務(wù)名db。 解決等幾十秒刷新頁面檢查 compose 文件里 host 是否為服務(wù)名docker compose logs db確認(rèn) MySQL 是否 ready。現(xiàn)象綁定掛載的目錄在容器里看不到文件。原因SELinux 或 AppArmor 攔截或者宿主機(jī)路徑寫成了相對路徑。 解決Ubuntu 上檢查 AppArmor 狀態(tài)掛載路徑用$(pwd)展開成絕對路徑SELinux 系統(tǒng)加:z或:Z標(biāo)簽?,F(xiàn)象docker build時npm install失敗報網(wǎng)絡(luò)錯誤。原因構(gòu)建容器內(nèi)的 DNS 配置和宿主機(jī)不一致或者基礎(chǔ)鏡像的包管理器源不可達(dá)。 解決在 Dockerfile 里換源或者構(gòu)建時加--networkhost讓構(gòu)建容器用宿主機(jī)網(wǎng)絡(luò)。6.2 從單機(jī)到編排的進(jìn)階路線這份指南最后給了學(xué)習(xí)路徑官方文檔、Play with Docker 實驗環(huán)境、網(wǎng)絡(luò)模式、Compose、Kubernetes、CI/CD。按我的經(jīng)驗順序應(yīng)該是先把docker run和docker compose用熟再碰網(wǎng)絡(luò)模式。bridge 模式是默認(rèn)host 模式讓容器直接用宿主機(jī)網(wǎng)絡(luò)性能好但端口沖突風(fēng)險高none 模式適合完全隔離的場景。Kubernetes 不用急著上單機(jī) compose 能跑通三五個服務(wù)之后再理解 Pod、Service、Deployment 會順很多。驗證自己是否真的掌握了可以試一個具體技巧用docker compose起一套 WordPress然后故意把db服務(wù)的卷刪掉觀察數(shù)據(jù)丟失的過程再用綁定掛載把 WordPress 的wp-content目錄映射到宿主機(jī)改主題文件即時生效。這一套走下來數(shù)據(jù)卷和綁定掛載的區(qū)別就不用背了。從那以后我每次寫 compose 文件都強(qiáng)制先跑一遍docker compose config檢查語法再up -d最后logs -f盯一分鐘——這個習(xí)慣幫我省掉了至少三次“以為起來了其實在反復(fù)重啟”的排查時間。希望幫到你。本文還有配套的精品資源點擊獲取