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