下Docker安裝與核心概念實(shí)戰(zhàn)指南)
1. 從“為什么需要Docker”開(kāi)始聊起如果你在Linux服務(wù)器上折騰過(guò)軟件部署大概率經(jīng)歷過(guò)這樣的場(chǎng)景為了部署一個(gè)應(yīng)用你需要先安裝特定版本的Python然后安裝一堆依賴包結(jié)果發(fā)現(xiàn)某個(gè)依賴包和系統(tǒng)里另一個(gè)服務(wù)的依賴版本沖突導(dǎo)致整個(gè)環(huán)境崩掉?;蛘吣阍谝慌_(tái)Ubuntu 22.04上跑得好好的服務(wù)遷移到CentOS 7上就各種報(bào)錯(cuò)光是排查環(huán)境差異就耗掉大半天。這種“在我機(jī)器上能跑”的困境是每個(gè)運(yùn)維和開(kāi)發(fā)者都頭疼的問(wèn)題。Docker的出現(xiàn)就是為了解決這個(gè)核心痛點(diǎn)。它不是一個(gè)輕量級(jí)的虛擬機(jī)而是一個(gè)容器化技術(shù)。你可以把它理解為一個(gè)超級(jí)輕便、標(biāo)準(zhǔn)化的“軟件集裝箱”。這個(gè)集裝箱里打包了你的應(yīng)用代碼、運(yùn)行環(huán)境、系統(tǒng)工具、系統(tǒng)庫(kù)和設(shè)置。無(wú)論這個(gè)集裝箱被運(yùn)到哪臺(tái)支持Docker的Linux機(jī)器上我們稱之為“宿主機(jī)”它都能以完全一致的方式運(yùn)行起來(lái)。這徹底解決了環(huán)境不一致的問(wèn)題讓開(kāi)發(fā)、測(cè)試、生產(chǎn)環(huán)境的部署變得極其簡(jiǎn)單和可靠。我最早接觸Docker是在一個(gè)微服務(wù)項(xiàng)目里當(dāng)時(shí)十幾個(gè)服務(wù)每個(gè)服務(wù)的依賴環(huán)境都不同手動(dòng)部署簡(jiǎn)直是噩夢(mèng)。自從用上Docker所有服務(wù)的環(huán)境都被固化在鏡像里通過(guò)一個(gè)簡(jiǎn)單的docker-compose up命令就能拉起整個(gè)集群部署時(shí)間從幾小時(shí)縮短到幾分鐘。這種效率的提升是革命性的。所以無(wú)論你是想學(xué)習(xí)一項(xiàng)熱門(mén)技術(shù)還是切實(shí)想提升自己的開(kāi)發(fā)和部署效率掌握Linux下的Docker都是非常值得投入時(shí)間的一步。2. 安裝前的準(zhǔn)備理清思路與避坑指南在動(dòng)手安裝Docker之前有幾個(gè)關(guān)鍵點(diǎn)必須搞清楚這能幫你避開(kāi)后面90%的坑。很多人一上來(lái)就照著教程敲命令結(jié)果遇到各種“virtualization support not detected”或者權(quán)限問(wèn)題其實(shí)根源都在準(zhǔn)備階段沒(méi)做好。首先明確你的Linux發(fā)行版和版本。Docker對(duì)主流發(fā)行版的支持都很好但安裝方式略有不同。最常見(jiàn)的是基于Debian的如Ubuntu、Debian和基于RPM的如CentOS、RHEL、Fedora。你需要用cat /etc/os-release命令確認(rèn)一下。這篇文章的實(shí)操部分會(huì)以Ubuntu 22.04 LTS和CentOS 7這兩個(gè)最典型的系統(tǒng)為例進(jìn)行講解其他發(fā)行版可以舉一反三。其次理解Docker的架構(gòu)和核心概念。Docker采用的是客戶端-服務(wù)器C/S架構(gòu)。我們平時(shí)在命令行里敲的docker命令其實(shí)是Docker客戶端Client。它通過(guò)REST API與一個(gè)常駐后臺(tái)進(jìn)程通信這個(gè)后臺(tái)進(jìn)程就是Docker守護(hù)進(jìn)程Daemon它負(fù)責(zé)創(chuàng)建、運(yùn)行和管理容器。我們安裝Docker主要就是安裝這個(gè)守護(hù)進(jìn)程、客戶端以及相關(guān)的工具鏈。最后也是最重要的檢查系統(tǒng)環(huán)境。這里有兩個(gè)大坑內(nèi)核版本Docker需要較新的Linux內(nèi)核來(lái)支持其底層特性如cgroups、namespaces。對(duì)于生產(chǎn)環(huán)境建議內(nèi)核版本在3.10以上。用uname -r查看。存儲(chǔ)驅(qū)動(dòng)Docker鏡像和容器數(shù)據(jù)需要存儲(chǔ)驅(qū)動(dòng)來(lái)管理。對(duì)于較新的發(fā)行版默認(rèn)的overlay2驅(qū)動(dòng)是首選性能最好。但有些舊系統(tǒng)或云主機(jī)可能用了devicemapper這可能會(huì)帶來(lái)性能問(wèn)題。安裝后需要確認(rèn)。注意網(wǎng)上很多教程會(huì)提到要“開(kāi)啟虛擬化支持”這通常是針對(duì)在Windows或macOS上安裝Docker Desktop時(shí)的要求。在純Linux環(huán)境下安裝Docker Engine也就是我們常說(shuō)的Docker并不需要CPU的虛擬化技術(shù)如Intel VT-x/AMD-V。Docker容器直接共享宿主機(jī)內(nèi)核利用的是Linux內(nèi)核的cgroup和namespace等特性來(lái)實(shí)現(xiàn)隔離這與虛擬機(jī)VM的硬件虛擬化是完全不同的技術(shù)路線。所以如果你在Linux主機(jī)上遇到類似“virtualization support not detected”的錯(cuò)誤提示那很可能是你錯(cuò)誤地嘗試安裝Docker Desktop for Linux或者混淆了概念。在Linux上我們安裝的是原生的Docker Engine。3. Ubuntu 22.04 系統(tǒng)下的Docker安裝詳解Ubuntu是個(gè)人學(xué)習(xí)和開(kāi)發(fā)環(huán)境中使用最廣泛的Linux發(fā)行版其軟件包管理工具apt非常方便。下面我們走一遍最穩(wěn)妥的安裝流程我會(huì)解釋每一步的作用。3.1 卸載舊版本與配置倉(cāng)庫(kù)第一步永遠(yuǎn)是清理戰(zhàn)場(chǎng)避免舊版本殘留導(dǎo)致沖突。即使你是新系統(tǒng)執(zhí)行一下也無(wú)妨。sudo apt-get remove docker docker-engine docker.io containerd runc這條命令移除了可能存在的舊版Docker包。containerd和runc是Docker依賴的底層容器運(yùn)行時(shí)我們后續(xù)會(huì)安裝更新的版本。接下來(lái)我們需要讓apt知道從哪里獲取Docker官方軟件包。Docker官方維護(hù)了一個(gè)APT倉(cāng)庫(kù)比Ubuntu自帶源中的版本更新、更穩(wěn)定。# 更新apt包索引并安裝一些工具這些工具允許apt通過(guò)HTTPS使用倉(cāng)庫(kù) sudo apt-get update sudo apt-get install \ ca-certificates \ curl \ gnupg \ lsb-release # 添加Docker官方的GPG密鑰。GPG密鑰用于驗(yàn)證軟件包的簽名確保你下載的包是官方發(fā)布的沒(méi)有被篡改。 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 設(shè)置穩(wěn)定版?zhèn)}庫(kù)。這里將倉(cāng)庫(kù)地址寫(xiě)入/etc/apt/sources.list.d/docker.list文件。 echo \ deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null這里有個(gè)細(xì)節(jié)$(lsb_release -cs)會(huì)自動(dòng)獲取你的Ubuntu代號(hào)比如jammy對(duì)應(yīng)22.04。這確保了倉(cāng)庫(kù)地址與你的系統(tǒng)版本匹配。3.2 安裝Docker Engine倉(cāng)庫(kù)配置好后安裝就很簡(jiǎn)單了。# 再次更新apt包索引這次它會(huì)讀取我們剛添加的Docker倉(cāng)庫(kù)信息。 sudo apt-get update # 安裝Docker Engine、命令行工具cli、containerd以及docker-compose-plugin。 # 注意包名是docker-ce社區(qū)版docker-ee是企業(yè)版。 sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin執(zhí)行這個(gè)命令后apt會(huì)自動(dòng)處理所有依賴。安裝完成后Docker守護(hù)進(jìn)程會(huì)自動(dòng)啟動(dòng)。3.3 驗(yàn)證安裝與權(quán)限配置安裝是否成功跑一個(gè)最經(jīng)典的測(cè)試鏡像就知道了。sudo docker run hello-world如果看到“Hello from Docker!”等歡迎信息說(shuō)明Docker已經(jīng)成功安裝并可以拉取和運(yùn)行容器了。但每次命令都要加sudo很麻煩而且有安全風(fēng)險(xiǎn)。通常我們會(huì)將當(dāng)前用戶加入docker用戶組這樣就能直接執(zhí)行docker命令。# 創(chuàng)建docker用戶組通常安裝時(shí)已自動(dòng)創(chuàng)建 sudo groupadd docker # 將當(dāng)前用戶加入docker組 sudo usermod -aG docker $USER關(guān)鍵一步退出當(dāng)前終端并重新登錄或者新開(kāi)一個(gè)終端用戶組的更改才會(huì)生效。之后你就可以不用sudo直接運(yùn)行docker ps等命令了。驗(yàn)證一下docker run --rm ubuntu:22.04 /bin/echo Hello, Docker!能成功輸出信息說(shuō)明權(quán)限配置正確。4. CentOS 7 系統(tǒng)下的Docker安裝與差異點(diǎn)處理CentOS 7以及RHEL 7在企業(yè)服務(wù)器中非常常見(jiàn)但它的內(nèi)核版本相對(duì)較老且使用yum作為包管理器安裝過(guò)程與Ubuntu有顯著區(qū)別。4.1 清理環(huán)境與添加倉(cāng)庫(kù)CentOS的Extras倉(cāng)庫(kù)提供了一個(gè)舊版本的docker包實(shí)際上是docker.io但版本非常老舊我們一定要先卸載它然后使用Docker官方倉(cāng)庫(kù)。# 卸載舊版本 sudo yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine # 安裝yum工具包它提供了yum-config-manager工具用于管理倉(cāng)庫(kù)。 sudo yum install -y yum-utils # 添加Docker官方倉(cāng)庫(kù) sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo4.2 安裝Docker Engine及可能的內(nèi)核升級(jí)CentOS 7默認(rèn)內(nèi)核是3.10雖然滿足Docker的最低要求但某些新特性可能不支持。如果條件允許建議升級(jí)到更新的內(nèi)核如ELRepo倉(cāng)庫(kù)的長(zhǎng)期支持版內(nèi)核。這里我們先按默認(rèn)內(nèi)核安裝。# 安裝Docker Engine sudo yum install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin如果安裝過(guò)程中提示container-selinux版本沖突這是因?yàn)镈ocker依賴的container-selinux版本高于CentOS默認(rèn)倉(cāng)庫(kù)提供的。你需要從CentOS Extras倉(cāng)庫(kù)安裝一個(gè)特定版本或者先安裝centos-release-extras包。一個(gè)常見(jiàn)的解決命令是sudo yum install -y https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-version.rpm # 然后再安裝docker-ce具體版本號(hào)需要去Docker倉(cāng)庫(kù)查看。這是CentOS 7安裝Docker時(shí)最常見(jiàn)的坑。4.3 啟動(dòng)服務(wù)與配置防火墻CentOS使用systemd管理服務(wù)且默認(rèn)開(kāi)啟了防火墻firewalld需要額外配置。# 啟動(dòng)Docker守護(hù)進(jìn)程 sudo systemctl start docker # 設(shè)置開(kāi)機(jī)自啟 sudo systemctl enable docker # 驗(yàn)證安裝 sudo docker run hello-world防火墻配置Docker守護(hù)進(jìn)程默認(rèn)會(huì)創(chuàng)建一個(gè)docker0的網(wǎng)橋容器通過(guò)它進(jìn)行網(wǎng)絡(luò)通信。為了讓容器能與外界或宿主機(jī)正常通信需要在防火墻中放行相關(guān)流量。# 永久放行Docker服務(wù)使用的端口范圍默認(rèn)是2375/2376但通常我們不用 # 更常見(jiàn)的做法是信任docker0網(wǎng)橋的流量 sudo firewall-cmd --permanent --zonetrusted --add-interfacedocker0 sudo firewall-cmd --reload如果你在容器內(nèi)運(yùn)行了Web服務(wù)如映射了80端口還需要在防火墻中放行對(duì)應(yīng)的宿主機(jī)端口sudo firewall-cmd --permanent --add-port80/tcp sudo firewall-cmd --reload同樣記得將用戶加入docker組以避免sudosudo groupadd docker sudo usermod -aG docker $USER # 重新登錄后生效5. Docker核心概念與基礎(chǔ)命令實(shí)戰(zhàn)安裝好了我們來(lái)真正用起來(lái)。要熟練使用Docker必須理解三個(gè)核心概念鏡像Image、容器Container、倉(cāng)庫(kù)Registry。它們的關(guān)系就像面向?qū)ο缶幊讨械念惡蛯?duì)象。鏡像Image一個(gè)只讀的模板里面包含了運(yùn)行應(yīng)用所需的代碼、庫(kù)、環(huán)境變量和配置文件。它相當(dāng)于一個(gè)“類”的定義。例如ubuntu:22.04,nginx:latest,python:3.9-slim。容器Container鏡像的一個(gè)運(yùn)行實(shí)例。你可以創(chuàng)建、啟動(dòng)、停止、刪除容器。容器與容器之間是相互隔離的。它相當(dāng)于根據(jù)“類”創(chuàng)建出來(lái)的一個(gè)“對(duì)象”。倉(cāng)庫(kù)Registry集中存放鏡像的地方。最大的公共倉(cāng)庫(kù)是 Docker Hub 你可以從這里拉取鏡像也可以推送自己的鏡像上去。私有的倉(cāng)庫(kù)可以自己搭建比如用Harbor。下面是一組你最需要掌握的基礎(chǔ)命令我附上了實(shí)際使用場(chǎng)景和解釋。5.1 鏡像相關(guān)操作# 從倉(cāng)庫(kù)拉取鏡像。如果不指定標(biāo)簽?zāi)J(rèn)拉取 latest。 # 建議生產(chǎn)環(huán)境總是指定明確的版本標(biāo)簽避免因latest更新導(dǎo)致意外。 docker pull nginx:1.23-alpine # 列出本地已下載的鏡像 docker images # 或者使用更強(qiáng)大的新命令 docker image ls docker image ls # 搜索Docker Hub上的鏡像通常直接去網(wǎng)站搜更直觀 docker search mysql # 刪除本地鏡像。如果鏡像有對(duì)應(yīng)的容器即使已停止需要先刪除容器才能刪除鏡像。 # 使用 -f 可以強(qiáng)制刪除但慎用。 docker rmi nginx:1.23-alpine # 刪除所有未被容器使用的鏡像懸空鏡像 docker image prune # 刪除所有未被使用的鏡像包括未被任何容器引用的鏡像 docker image prune -a5.2 容器生命周期管理這是最核心的部分容器就像一個(gè)輕量級(jí)的進(jìn)程。# 運(yùn)行一個(gè)容器 # -d: 后臺(tái)運(yùn)行detached mode # --name mynginx: 給容器起個(gè)名字否則Docker會(huì)隨機(jī)分配一個(gè) # -p 8080:80: 端口映射將宿主機(jī)的8080端口映射到容器的80端口 # nginx:alpine: 使用的鏡像 docker run -d --name mynginx -p 8080:80 nginx:alpine # 此時(shí)在瀏覽器訪問(wèn) http://你的服務(wù)器IP:8080就能看到Nginx歡迎頁(yè)。 # 列出正在運(yùn)行的容器 docker ps # 列出所有容器包括已停止的 docker ps -a # 停止一個(gè)運(yùn)行中的容器 docker stop mynginx # 啟動(dòng)一個(gè)已停止的容器 docker start mynginx # 重啟容器 docker restart mynginx # 進(jìn)入一個(gè)正在運(yùn)行的容器的命令行終端 # -it 是 -i (交互式) 和 -t (分配一個(gè)偽終端) 的組合讓你可以像SSH一樣操作容器。 docker exec -it mynginx /bin/sh # 對(duì)于基于Alpine的鏡像shell通常是/bin/sh對(duì)于Ubuntu等是/bin/bash。 # 查看容器的日志輸出排查問(wèn)題非常有用 docker logs mynginx # 實(shí)時(shí)查看日志類似 tail -f docker logs -f mynginx # 刪除一個(gè)已停止的容器 docker rm mynginx # 強(qiáng)制刪除一個(gè)運(yùn)行中的容器不推薦應(yīng)先停止 docker rm -f mynginx # 刪除所有已停止的容器清理空間 docker container prune5.3 容器與宿主機(jī)的數(shù)據(jù)交互容器默認(rèn)是“無(wú)狀態(tài)”的其內(nèi)部文件系統(tǒng)的改動(dòng)在容器刪除后會(huì)丟失。為了持久化數(shù)據(jù)如數(shù)據(jù)庫(kù)文件、配置文件、日志我們需要使用卷Volume或綁定掛載Bind Mount。卷Volume由Docker管理存儲(chǔ)在宿主機(jī)文件系統(tǒng)的某個(gè)區(qū)域通常是/var/lib/docker/volumes/與容器的生命周期解耦。這是持久化數(shù)據(jù)的推薦方式。# 創(chuàng)建一個(gè)名為 my-vol 的卷 docker volume create my-vol # 運(yùn)行容器并使用這個(gè)卷將容器內(nèi)的 /app/data 目錄掛載到卷上 docker run -d --name myapp -v my-vol:/app/data myapp-image # 即使 myapp 容器被刪除my-vol 卷及其數(shù)據(jù)依然存在可以被其他容器掛載。綁定掛載Bind Mount將宿主機(jī)上的一個(gè)特定目錄或文件直接掛載到容器中。常用于開(kāi)發(fā)環(huán)境方便在宿主機(jī)上修改代碼容器內(nèi)實(shí)時(shí)生效。# 將宿主機(jī)的 /home/user/project 目錄掛載到容器的 /app 目錄 docker run -d --name dev-app -v /home/user/project:/app dev-app-image # 現(xiàn)在你在宿主機(jī)上修改代碼容器內(nèi)的 /app 下文件也會(huì)同步變化。6. 使用Dockerfile定制專屬鏡像從公共鏡像倉(cāng)庫(kù)拉取鏡像很方便但更多時(shí)候我們需要構(gòu)建自己的鏡像比如部署自己的Python應(yīng)用、Java應(yīng)用。這就需要編寫(xiě)Dockerfile。Dockerfile是一個(gè)文本文件包含了一條條構(gòu)建鏡像所需的指令。下面我們以一個(gè)簡(jiǎn)單的Python Flask應(yīng)用為例手把手構(gòu)建一個(gè)鏡像。項(xiàng)目結(jié)構(gòu)myflaskapp/ ├── app.py ├── requirements.txt └── Dockerfileapp.py(一個(gè)最簡(jiǎn)單的Flask應(yīng)用)from flask import Flask app Flask(__name__) app.route(/) def hello(): return Hello, Docker! if __name__ __main__: app.run(host0.0.0.0, port5000)requirements.txtFlask2.3.2Dockerfile# 第一階段使用官方Python輕量級(jí)鏡像作為構(gòu)建環(huán)境 FROM python:3.9-slim as builder # 設(shè)置工作目錄后續(xù)命令都在這個(gè)目錄下執(zhí)行 WORKDIR /app # 將依賴文件復(fù)制到工作目錄 COPY requirements.txt . # 安裝依賴。使用清華PyPI鏡像加速并將依賴安裝到 /usr/local RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt # 第二階段使用更小的運(yùn)行時(shí)鏡像只復(fù)制必要的文件 FROM python:3.9-slim # 設(shè)置工作目錄 WORKDIR /app # 從構(gòu)建階段復(fù)制已安裝的Python包 COPY --frombuilder /usr/local /usr/local # 復(fù)制應(yīng)用代碼 COPY . . # 聲明容器運(yùn)行時(shí)監(jiān)聽(tīng)的端口 EXPOSE 5000 # 定義容器啟動(dòng)時(shí)執(zhí)行的命令 CMD [python, app.py]逐行解釋FROM: 指定基礎(chǔ)鏡像。我們使用了兩階段構(gòu)建第一階段builder用于安裝依賴第二階段使用同一個(gè)基礎(chǔ)鏡像但只復(fù)制安裝結(jié)果可以顯著減小最終鏡像體積。WORKDIR: 設(shè)置工作目錄相當(dāng)于cd到這個(gè)目錄。COPY: 將宿主機(jī)文件復(fù)制到鏡像內(nèi)。RUN: 在構(gòu)建鏡像時(shí)執(zhí)行的命令這里用來(lái)安裝依賴。我們使用了國(guó)內(nèi)鏡像源加速下載。EXPOSE: 聲明容器打算使用的端口這是一個(gè)文檔性質(zhì)的說(shuō)明實(shí)際端口映射需要在docker run時(shí)用-p指定。CMD: 指定容器啟動(dòng)時(shí)默認(rèn)執(zhí)行的命令。一個(gè)Dockerfile中只能有一條CMD指令。構(gòu)建鏡像 在myflaskapp目錄下執(zhí)行# -t 給鏡像打標(biāo)簽格式為 名稱:標(biāo)簽標(biāo)簽?zāi)J(rèn)為 latest # . 表示Dockerfile所在的當(dāng)前目錄為構(gòu)建上下文 docker build -t my-flask-app:1.0 .運(yùn)行容器# 將宿主機(jī)的5000端口映射到容器的5000端口 docker run -d --name myapp -p 5000:5000 my-flask-app:1.0訪問(wèn)http://localhost:5000就能看到“Hello, Docker!”了。7. 使用Docker Compose編排多容器應(yīng)用現(xiàn)實(shí)中的應(yīng)用很少是單個(gè)容器通常由多個(gè)服務(wù)組成比如一個(gè)Web應(yīng)用需要搭配數(shù)據(jù)庫(kù)、緩存等。手動(dòng)用docker run啟動(dòng)每一個(gè)容器并配置網(wǎng)絡(luò)鏈接非常繁瑣。Docker Compose就是用來(lái)定義和運(yùn)行多容器Docker應(yīng)用的工具。它使用一個(gè)YAML文件默認(rèn)docker-compose.yml來(lái)配置所有服務(wù)。假設(shè)我們有一個(gè)WordPress博客需要WordPress容器和MySQL數(shù)據(jù)庫(kù)容器。創(chuàng)建一個(gè)docker-compose.yml文件version: 3.8 # 指定Compose文件格式版本 services: # 數(shù)據(jù)庫(kù)服務(wù) db: image: mysql:8.0 # 容器重啟策略除非手動(dòng)停止否則總是重啟 restart: always environment: # 設(shè)置MySQL的root密碼和環(huán)境變量這是必須的 MYSQL_ROOT_PASSWORD: somewordpress MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress # 命名卷用于持久化數(shù)據(jù)庫(kù)數(shù)據(jù) volumes: - db_data:/var/lib/mysql # 自定義網(wǎng)絡(luò)讓服務(wù)間可以通過(guò)服務(wù)名通信 networks: - wp-network # WordPress服務(wù) wordpress: depends_on: - db # 聲明依賴確保db服務(wù)先啟動(dòng) image: wordpress:latest restart: always ports: - 8080:80 # 將宿主機(jī)的8080端口映射到WordPress容器的80端口 environment: # 告訴WordPress如何連接數(shù)據(jù)庫(kù)這里db就是上面定義的服務(wù)名 WORDPRESS_DB_HOST: db:3306 WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes: # 綁定掛載將當(dāng)前目錄下的wp-content目錄掛載方便主題/插件管理 - ./wp-content:/var/www/html/wp-content networks: - wp-network # 定義卷Docker Compose會(huì)自動(dòng)創(chuàng)建和管理它 volumes: db_data: # 定義網(wǎng)絡(luò)Docker Compose會(huì)自動(dòng)創(chuàng)建一個(gè)名為項(xiàng)目名_wp-network的網(wǎng)絡(luò) networks: wp-network: driver: bridge運(yùn)行與管理 在包含docker-compose.yml的目錄下執(zhí)行以下命令# 啟動(dòng)所有服務(wù)后臺(tái)運(yùn)行 docker-compose up -d # 查看服務(wù)狀態(tài) docker-compose ps # 查看所有服務(wù)的日志 docker-compose logs # 查看特定服務(wù)如wordpress的日志 docker-compose logs wordpress # 停止所有服務(wù) docker-compose stop # 停止并刪除所有容器、網(wǎng)絡(luò)但保留卷 docker-compose down # 停止并刪除所有容器、網(wǎng)絡(luò)、卷數(shù)據(jù)也會(huì)被刪除 docker-compose down -vDocker Compose極大地簡(jiǎn)化了多服務(wù)應(yīng)用的部署和管理是開(kāi)發(fā)測(cè)試環(huán)境的利器。對(duì)于更復(fù)雜的生產(chǎn)環(huán)境集群編排則需要用到Kubernetes (K8s)或Docker Swarm。8. 生產(chǎn)環(huán)境部署的進(jìn)階考量與優(yōu)化將Docker用于個(gè)人學(xué)習(xí)或開(kāi)發(fā)很簡(jiǎn)單但一旦要上生產(chǎn)環(huán)境就需要考慮更多因素安全性、性能、日志、監(jiān)控、鏡像倉(cāng)庫(kù)等。1. 鏡像優(yōu)化與安全掃描使用多階段構(gòu)建如上文Flask例子所示可以大幅減小最終鏡像體積減少攻擊面。使用特定標(biāo)簽不要使用latest標(biāo)簽而應(yīng)使用明確的版本號(hào)如python:3.9.16-slim-bullseye。使用非root用戶運(yùn)行容器在Dockerfile中創(chuàng)建并使用非root用戶。RUN groupadd -r appuser useradd -r -g appuser appuser USER appuser定期掃描鏡像漏洞可以使用docker scan命令集成Snyk或第三方工具如Trivy、Clair掃描鏡像中的已知安全漏洞。2. 日志管理容器默認(rèn)將日志輸出到stdout和stderrDocker守護(hù)進(jìn)程會(huì)捕獲并存儲(chǔ)。在生產(chǎn)環(huán)境中需要將日志集中收集和管理。使用日志驅(qū)動(dòng)可以配置Docker守護(hù)進(jìn)程將日志發(fā)送到j(luò)son-file默認(rèn)、syslog、journald或fluentd等。使用Docker Compose的logging配置可以限制日志文件大小防止磁盤(pán)被撐滿。services: myapp: image: myapp logging: driver: json-file options: max-size: 10m max-file: 33. 資源限制防止單個(gè)容器耗盡宿主機(jī)資源。# 運(yùn)行容器時(shí)限制CPU和內(nèi)存 docker run -d --name myapp \ --cpus1.5 \ # 限制使用1.5個(gè)CPU核心 --memory512m \ # 限制內(nèi)存為512MB --memory-swap1g \ # 限制內(nèi)存交換分區(qū)總量為1GB myapp-image4. 使用私有鏡像倉(cāng)庫(kù)生產(chǎn)環(huán)境不應(yīng)直接從Docker Hub拉取鏡像。應(yīng)該搭建私有倉(cāng)庫(kù)如Harbor、Nexus或使用云服務(wù)商提供的倉(cāng)庫(kù)如ACR、ECR、GCR。登錄私有倉(cāng)庫(kù)docker login myregistry.example.com給鏡像打上私有倉(cāng)庫(kù)標(biāo)簽docker tag myapp:1.0 myregistry.example.com/myapp:1.0推送鏡像docker push myregistry.example.com/myapp:1.0拉取鏡像docker pull myregistry.example.com/myapp:1.05. 服務(wù)發(fā)現(xiàn)與網(wǎng)絡(luò)對(duì)于多主機(jī)集群Docker原生的bridge網(wǎng)絡(luò)不夠用。需要結(jié)合Overlay網(wǎng)絡(luò)Swarm模式或直接使用Kubernetes的CNI容器網(wǎng)絡(luò)接口插件來(lái)管理跨主機(jī)的容器網(wǎng)絡(luò)。從單機(jī)安裝到多容器編排再到生產(chǎn)環(huán)境的考量Docker的學(xué)習(xí)路徑是循序漸進(jìn)的。我個(gè)人的經(jīng)驗(yàn)是先在本機(jī)或虛擬機(jī)里把單容器和Docker Compose玩熟練理解鏡像、容器、數(shù)據(jù)卷、網(wǎng)絡(luò)這些核心概念。當(dāng)你的應(yīng)用變得復(fù)雜需要高可用、自動(dòng)伸縮時(shí)再去探索Kubernetes的世界。Docker是這一切的基石扎實(shí)的基礎(chǔ)會(huì)讓你后續(xù)的學(xué)習(xí)輕松很多。在實(shí)際操作中最常遇到的坑往往是權(quán)限問(wèn)題Got permission denied、端口沖突、鏡像拉取慢記得配置國(guó)內(nèi)鏡像加速器以及磁盤(pán)空間不足記得定期prune。多動(dòng)手多查日志解決問(wèn)題的過(guò)程本身就是最好的學(xué)習(xí)。