在Docker環(huán)境中如何運行自己的代碼
一、什么是 Docker?
1.1 Docker 的定義與核心定位
Docker 是由 Docker Inc.(后被 Mirantis 收購)開發(fā)的一款開源的容器化平臺,基于 Go 語言開發(fā),遵循 Apache 2.0 開源協(xié)議。其核心定位是:將應用程序及其依賴環(huán)境打包成輕量級、可移植、自包含的容器,使得應用可以在任何支持 Docker 的環(huán)境中以相同的方式運行。
通俗來講,Docker 就像一個 “標準化的集裝箱”:無論你的應用是 Python 寫的 Web 服務、Node.js 開發(fā)的前端項目,還是 Java 構建的微服務,都可以被裝進這個 “集裝箱” 里。這個 “集裝箱” 包含了應用運行所需的所有東西 —— 代碼、運行時、系統(tǒng)工具、系統(tǒng)庫,只要有 Docker 運行環(huán)境,這個 “集裝箱” 就能無縫運行,無需擔心環(huán)境差異。
1.2 Docker 的核心架構
Docker 采用客戶端 - 服務器(C/S)架構,核心組件包括:
- Docker Client(客戶端):用戶交互的入口,通過命令行(
docker命令)或 API 向 Docker Daemon 發(fā)送指令(如構建鏡像、啟動容器); - Docker Daemon(守護進程):運行在宿主機的后臺進程,負責處理客戶端的請求,管理鏡像、容器、網(wǎng)絡、數(shù)據(jù)卷等核心資源;
- Docker Registry(鏡像倉庫):存儲 Docker 鏡像的倉庫,分為公有倉庫(如 Docker Hub)和私有倉庫(如企業(yè)內部倉庫);
- Containerd:底層容器運行時,負責容器的創(chuàng)建、啟動、停止等生命周期管理,Docker Daemon 不再直接操作容器,而是通過 Containerd 調用 RunC;
- RunC:輕量級的容器運行時,遵循 OCI(開放容器倡議)標準,是容器運行的核心執(zhí)行器。
核心交互流程:用戶通過 Docker Client 輸入 docker run 命令 → Docker Daemon 接收指令后,從 Registry 拉取鏡像(若本地無)→ 調用 Containerd 創(chuàng)建容器 → RunC 啟動容器進程,完成應用運行。
二、為什么要使用 Docker?—— 解決開發(fā)部署的核心痛點
2.1 徹底終結 “環(huán)境不一致” 的噩夢
“在我本地能跑,到測試環(huán)境就報錯” 是開發(fā)人員的經(jīng)典吐槽,根源在于開發(fā)、測試、生產(chǎn)環(huán)境的差異:
- 開發(fā)用 macOS + Python 3.8,測試服務器是 CentOS 7 + Python 3.6,依賴包版本沖突導致代碼運行異常;
- 前端項目依賴 Node.js 16,運維部署時用了 Node.js 18,打包后的代碼出現(xiàn)兼容性問題;
- 數(shù)據(jù)庫版本不一致:開發(fā)用 MySQL 8.0,生產(chǎn)用 MySQL 5.7,SQL 語法不兼容導致功能失效。
Docker 的解決方案是:將應用 + 運行環(huán)境打包成鏡像,鏡像在任何支持 Docker 的環(huán)境中運行結果一致。無論你是在 macOS、Windows、Linux 還是云服務器上運行,只要鏡像相同,應用行為就完全一致,真正實現(xiàn) “一次構建,到處運行”。
三、核心概念辨析:虛擬機、Docker 容器與鏡像
要掌握 Docker,必須先理清三個核心概念:虛擬機、Docker 容器、Docker 鏡像,以及它們之間的關系。
3.1 傳統(tǒng)虛擬機:重量級的環(huán)境隔離方案
虛擬機(VM)是通過虛擬化技術在物理服務器上模擬出的獨立操作系統(tǒng)實例,核心依賴 Hypervisor(虛擬化管理程序,如 VMware、KVM、VirtualBox)。
3.1.1 虛擬機的架構
- 物理機(Host Machine):底層的硬件服務器,提供 CPU、內存、存儲、網(wǎng)絡等物理資源;
- Hypervisor:運行在物理機上的虛擬化層,負責將物理資源分配給不同的虛擬機;
- 客戶機(Guest Machine):虛擬機實例,包含完整的操作系統(tǒng)(如 Windows、Linux)和應用程序;
- Guest OS:虛擬機內的操作系統(tǒng),每個虛擬機都有獨立的內核和系統(tǒng)庫。
3.1.2 虛擬機的特點
- 完全隔離:每個虛擬機擁有獨立的內核、文件系統(tǒng)、網(wǎng)絡,與其他虛擬機和宿主機完全隔離;
- 重量級:需要模擬完整的硬件和操作系統(tǒng),啟動時間長(分鐘級),資源占用高(每個虛擬機需分配固定的 CPU、內存);
- 兼容性好:可運行任何操作系統(tǒng)和應用,不受宿主機系統(tǒng)限制。
3.2 Docker 容器:輕量級的進程隔離
Docker 容器是基于 Linux 內核技術實現(xiàn)的輕量級隔離環(huán)境,本質上是宿主機上的一組受限制的進程。
3.2.1 容器的核心隔離技術
Docker 容器的隔離性依賴 Linux 內核的兩大核心特性:
- Namespace:實現(xiàn)資源隔離,包括 PID(進程 ID)、NET(網(wǎng)絡)、MNT(文件系統(tǒng))、UTS(主機名)、IPC(進程間通信)、USER(用戶)等 Namespace。每個容器擁有獨立的 Namespace,只能看到自己的進程、網(wǎng)絡、文件系統(tǒng),無法感知宿主機或其他容器的資源;
- Cgroup(Control Group):實現(xiàn)資源限制,可限制容器的 CPU、內存、磁盤 I/O、網(wǎng)絡帶寬等資源,避免容器搶占宿主機資源。
3.2.2 容器的特點
- 輕量級:無需模擬硬件和操作系統(tǒng)內核,共享宿主機內核,啟動時間短(毫秒級),資源占用低(按需分配資源,無需固定分配);
- 高效隔離:進程級隔離,隔離性略弱于虛擬機,但足以滿足絕大多數(shù)應用場景;
- 可移植性:基于鏡像運行,可在任何支持 Docker 的環(huán)境中遷移;
- 快速擴縮容:容器創(chuàng)建 / 銷毀速度快,可快速響應業(yè)務擴縮容需求。
3.3 Docker 鏡像:容器的 “只讀模板”
Docker 鏡像(Image)是創(chuàng)建 Docker 容器的只讀模板,包含了容器運行所需的所有文件系統(tǒng)、代碼、運行時、依賴、配置等。
3.3.1 鏡像的核心特性
- 只讀性:鏡像一旦構建完成,就無法修改,只能以只讀方式存在;
- 分層結構:鏡像基于 UnionFS(聯(lián)合文件系統(tǒng))實現(xiàn)分層存儲,每個層都是一個只讀的文件系統(tǒng)片段,多個鏡像可共享相同的層,節(jié)省存儲空間。例如:Python 3.9-alpine 鏡像包含基礎層(alpine 系統(tǒng))、Python 運行時層、依賴層,多個基于該鏡像的容器可共享這些層;
- 可復用性:鏡像可作為基礎模板,構建新的鏡像(如基于 Python 3.9-alpine 鏡像,添加自己的代碼和依賴,構建新的應用鏡像)。
3.4 虛擬機 vs Docker 容器:核心差異對比
| 特性 | 虛擬機 | Docker 容器 |
|---|---|---|
| 內核 | 每個虛擬機有獨立內核 | 共享宿主機內核(僅 Linux 容器) |
| 啟動時間 | 分鐘級 | 毫秒級 |
| 資源占用 | 高(固定分配 CPU / 內存) | 低(按需分配,共享資源) |
| 隔離級別 | 硬件級(完全隔離) | 進程級(內核級隔離) |
| 鏡像 / 鏡像體積 | 大(包含完整操作系統(tǒng),GB 級) | ?。▋H包含應用和依賴,MB 級) |
| 可移植性 | 差(依賴 Hypervisor) | 好(跨平臺運行) |
| 擴縮容效率 | 低(啟動慢,資源固定) | 高(啟動快,資源彈性分配) |
| 適用場景 | 需完全隔離的場景(如多操作系統(tǒng)運行) | 微服務、CI/CD、快速部署、環(huán)境標準化 |
3.5 Docker 容器與鏡像的關系:模板與實例
Docker 容器和鏡像的關系,類似于類與對象的關系(鏡像可以理解為一個生產(chǎn)容器的模具):
- 鏡像:相當于 “類”,是只讀的模板,定義了容器的結構和行為;
- 容器:相當于 “對象”,是鏡像的運行實例,基于鏡像創(chuàng)建,擁有可寫層(鏡像為只讀,容器在鏡像的基礎上添加一層可寫層,所有修改都在可寫層中進行)。
核心關系總結:
- 一個鏡像可以創(chuàng)建多個容器(一個類可以實例化多個對象);
- 容器啟動時,Docker 會加載鏡像的所有只讀層,并在頂部創(chuàng)建一個可寫層;
- 容器停止后,可寫層的數(shù)據(jù)不會丟失,重啟容器后仍可訪問;
- 刪除容器時,可寫層會被刪除,鏡像的只讀層不會受影響;
- 可通過
docker commit將容器的可寫層轉換為新的鏡像層,實現(xiàn)鏡像的更新。
示例:基于 python:3.9-alpine 鏡像創(chuàng)建兩個容器 A 和 B,A 和 B 共享鏡像的只讀層,各自擁有獨立的可寫層。修改 A 容器內的文件,只會影響 A 的可寫層,不會影響 B 容器和原始鏡像。
四、如何選擇并拉取合適的 Docker 鏡像?
鏡像是 Docker 運行的基礎,選擇合適的鏡像直接影響容器的穩(wěn)定性、體積和安全性。本節(jié)將詳細講解鏡像的選擇原則、拉取方法和本地管理。
4.1 鏡像的核心來源
4.1.1 公有鏡像倉庫:Docker Hub
Docker Hub(https://hub.docker.com/)是官方的公有鏡像倉庫,包含數(shù)百萬個官方和社區(qū)鏡像,是最主要的鏡像來源:
- 官方鏡像:由 Docker 官方或軟件廠商維護(如
python、node、nginx、mysql),安全性高、更新及時、兼容性好; - 社區(qū)鏡像:由開發(fā)者或社區(qū)維護,可能包含定制化配置,但需注意安全性(避免惡意鏡像)。
4.1.2 私有鏡像倉庫
企業(yè)內部通常會搭建私有鏡像倉庫(如 Docker Registry、Harbor),用于存儲內部定制的鏡像:
- 避免敏感代碼 / 配置泄露;
- 提高鏡像拉取速度(無需訪問公網(wǎng));
- 統(tǒng)一管理企業(yè)內部的鏡像版本。
4.2 選擇鏡像的核心原則
4.2.1 優(yōu)先選擇官方鏡像
官方鏡像經(jīng)過嚴格測試,安全性和穩(wěn)定性有保障,且有清晰的版本更新記錄。
例如:選擇 python:3.9-alpine 而非社區(qū)維護的 xxx/python:3.9。
4.2.2 選擇輕量化的鏡像版本
鏡像體積越小,拉取速度越快,占用存儲空間越少。常見的輕量化版本:
- alpine 版本:基于 Alpine Linux(輕量級 Linux 發(fā)行版,體積約 5MB),是最常用的輕量化版本,如
python:3.9-alpine、nginx:alpine; - slim 版本:精簡版,去掉了不必要的組件,體積介于 full 版本和 alpine 版本之間,如
python:3.9-slim; - full 版本:完整版本,包含所有組件,體積大,適合需要完整工具鏈的場景。
注意:alpine 版本可能缺少部分系統(tǒng)庫,若應用依賴特定庫(如 glibc),需手動安裝。
4.2.3 明確指定鏡像標簽,避免使用 latest
latest 是鏡像的默認標簽,指向最新版本,但無法保證版本的穩(wěn)定性(可能隨時更新)。生產(chǎn)環(huán)境中必須指定具體版本標簽,如 python:3.9.18-alpine 而非 python:latest。
標簽命名規(guī)則:通常包含 “主版本。次版本。補丁版本 - 系統(tǒng)版本”,如 node:18.18.2-alpine3.18。
4.2.4 關注鏡像的安全性
- 查看鏡像的漏洞掃描報告(Docker Hub 提供鏡像的安全掃描功能);
- 避免使用未知來源的社區(qū)鏡像,防止包含惡意代碼;
- 定期更新鏡像,修復已知漏洞。
4.2.5 考慮鏡像的維護性
選擇維護活躍的鏡像,避免使用已停止更新的版本(如 Python 2.7 已停止維護,應避免使用)??赏ㄟ^ Docker Hub 查看鏡像的 “Last Updated” 時間,判斷維護狀態(tài)。
4.3 不同場景的鏡像選擇示例
| 應用場景 | 推薦鏡像 | 選擇理由 |
|---|---|---|
| Python 微服務(生產(chǎn)) | python:3.9-alpine | 體積小、資源占用低,適合生產(chǎn)環(huán)境 |
| Python 開發(fā)環(huán)境 | python:3.9-slim | 包含基礎工具鏈,便于調試 |
| Node.js 前端項目部署 | node:18-alpine | 輕量化,適合打包和運行前端代碼 |
| Java Spring Boot 應用 | openjdk:17-jdk-alpine | 體積小,支持 Spring Boot 3.x |
| Nginx 靜態(tài)資源托管 | nginx:alpine | 輕量級,性能高,適合靜態(tài)資源部署 |
| MySQL 數(shù)據(jù)庫(測試) | mysql:5.7-alpine | 輕量化,適合測試環(huán)境 |
| MySQL 數(shù)據(jù)庫(生產(chǎn)) | mysql:8.0.36 | 完整版本,穩(wěn)定性高,支持生產(chǎn)環(huán)境特性 |
4.4 鏡像拉取的核心命令與實操
4.4.1 搜索鏡像
使用 docker search 命令搜索 Docker Hub 上的鏡像:
bash運行:
# 搜索 Python 鏡像 docker search python # 篩選官方鏡像(--filter=is-official=true) docker search --filter=is-official=true python # 篩選星數(shù)≥1000的鏡像(--filter=stars=1000) docker search --filter=stars=1000 python
4.4.2 拉取鏡像
使用 docker pull 命令拉取鏡像,格式:docker pull 鏡像名:標簽。
bash運行:
# 拉取官方 Python 3.9-alpine 鏡像 docker pull python:3.9-alpine # 拉取指定版本的 Nginx 鏡像 docker pull nginx:1.25.3-alpine # 拉取私有倉庫的鏡像(需先登錄) docker pull registry.example.com/my-app:v1.0
若不指定標簽,默認拉取 latest 標簽:
bash運行:
docker pull python # 等價于 docker pull python:latest
4.4.3 登錄私有鏡像倉庫
拉取 / 推送私有鏡像前,需先登錄倉庫:
bash運行:
# 登錄 Docker Hub docker login # 登錄私有倉庫 docker login registry.example.com
輸入用戶名和密碼后,登錄信息會保存在 ~/.docker/config.json 文件中。
4.5 鏡像的本地管理
4.5.1 查看本地鏡像
bash運行:
# 查看所有本地鏡像
docker images
# 精簡輸出格式(只顯示鏡像ID、名稱、標簽、大?。?
docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}"
# 查看鏡像的詳細信息
docker inspect python:3.9-alpine
4.5.2 重命名鏡像
使用 docker tag 命令為鏡像添加新標簽(常用于推送鏡像到私有倉庫):
bash運行:
# 格式:docker tag 原鏡像名:標簽 新鏡像名:標簽 docker tag python:3.9-alpine registry.example.com/my-python:3.9-alpine
4.5.3 刪除鏡像
使用 docker rmi 命令刪除本地鏡像:
bash運行:
# 刪除指定鏡像(通過鏡像名:標簽) docker rmi python:3.9-alpine # 刪除指定鏡像(通過鏡像ID) docker rmi 1234567890ab # 強制刪除(鏡像被容器使用時,需加 -f) docker rmi -f python:3.9-alpine # 刪除所有未使用的鏡像(清理空間) docker image prune -a
注意:刪除鏡像前,需先刪除基于該鏡像創(chuàng)建的容器(或強制刪除)。
4.5.4 查看鏡像構建歷史
使用 docker history 命令查看鏡像的分層構建歷史,可排查鏡像體積過大的原因:
bash運行:
docker history python:3.9-alpine
4.5.5 運行容器 / 退出容器 / 管理鏡像 / 啟動已停止容器
(一)運行容器
(docker run:基于鏡像創(chuàng)建 + 啟動新容器,核心是「run 鏡像」)
1. 基礎語法
bash 運行:
docker run [可選參數(shù)] <鏡像名/鏡像ID> [容器內要執(zhí)行的命令]
- 鏡像名 / ID:必須指定(比如
ubuntu:20.04、python:3.9-slim,或鏡像 ID 如f8c79dc85f05); - 可選參數(shù):控制容器的運行方式(交互式、后臺、命名、端口映射等);
- 容器內命令:可選,比如
bash(進入終端)、python app.py(運行腳本)。
2. 常用示例(從簡單到復雜)
| 場景 | 命令示例 | 說明 |
|---|---|---|
| 最簡運行(前臺) | docker run ubuntu:20.04 | 基于 ubuntu:20.04 鏡像創(chuàng)建容器,執(zhí)行鏡像默認命令(通常是 bash),但無終端交互,運行后立即退出 |
| 交互式運行(常用) | docker run -it ubuntu:20.04 bash | -it:-i(交互式輸入)+-t(分配終端),進入容器的 bash 終端,可執(zhí)行命令 |
| 后臺運行(守護態(tài)) | docker run -d --name my-ubuntu ubuntu:20.04 sleep 3600 | -d:后臺運行;--name:給容器命名(避免隨機名稱);sleep 3600:容器后臺運行 1 小時 |
| 端口映射 + 后臺運行 | docker run -d -p 8080:80 --name my-nginx nginx | -p 8080:80:主機 8080 端口映射到容器 80 端口,訪問主機 8080 = 訪問容器 80 |
3. 關鍵參數(shù)解釋
-it:必選(交互式操作),缺一則無法進入容器終端;-d:后臺運行(守護進程),容器在后臺執(zhí)行,不占用當前終端;--name:自定義容器名(如my-app),否則 Docker 會隨機生成名稱;-p:端口映射(主機端口:容器端口),對外暴露容器服務;-v:目錄掛載(主機目錄:容器目錄),實現(xiàn)主機和容器文件共享(如-v /host/data:/container/data)。
(二)退出容器
退出容器的核心是區(qū)分「是否停止容器」,取決于你運行容器的方式(前臺 / 后臺)。
1. 場景 1:交互式容器(-it 前臺運行,比如 docker run -it ubuntu bash)
| 退出方式 | 命令 / 操作 | 效果 |
|---|---|---|
| 停止容器并退出 | 在容器終端輸入 exit | 容器停止運行,回到 Linux 主機終端,容器狀態(tài)變?yōu)?nbsp;exited |
| 不停止容器并退出 | 按快捷鍵 Ctrl + P → Q | 容器繼續(xù)后臺運行(狀態(tài) up),僅退出容器終端,回到 Linux 主機終端 |
2. 場景 2:后臺容器(-d 運行,比如 docker run -d my-nginx)
后臺容器本身不占用終端,無需 “退出”,若要操作 / 停止:
bash 運行:
# 先進入后臺容器的終端(可選) docker exec -it my-nginx bash # 進入后可執(zhí)行命令,退出用 exit(僅退出終端,容器仍運行) # 停止后臺容器(徹底“退出”容器運行) docker stop my-nginx # 按容器名停止;也可用容器ID:docker stop <容器ID>
(三)“啟動已停止的容器”
docker run 是創(chuàng)建新容器(每次 run 都會生成新容器),而已停止的容器(比如 exit 后的容器)需要用 docker start 啟動,這才是 “運行已有容器” 的正確方式。
1. 先查看所有容器(找到已停止的容器)
bash 運行:
docker ps -a # -a:顯示所有容器(運行中+已停止) # 輸出示例: # CONTAINER ID IMAGE COMMAND STATUS NAMES # abc123 ubuntu:20.04 "bash" Exited (0) 5min ago my-ubuntu
2. 啟動已停止的容器(「運行容器」的正確方式)
bash 運行:
# 語法:docker start [可選參數(shù)] <容器名/容器ID> docker start my-ubuntu # 啟動名為my-ubuntu的容器(后臺運行) docker start -i my-ubuntu # -i:交互式啟動(前臺運行,可輸入命令)
3. 重啟容器(停止 + 啟動)
bash 運行:
docker restart my-ubuntu # 重啟容器(無論當前是否運行)
(四)刪除容器 / 鏡像
1. 刪除容器(需先停止,或強制刪除)
bash 運行:
# 先停止容器 docker stop my-ubuntu # 刪除容器 docker rm my-ubuntu # 強制刪除運行中的容器(不推薦,除非緊急) docker rm -f my-ubuntu # 批量刪除所有已停止容器(常用) docker rm $(docker ps -aq --filter status=exited)
2. 刪除鏡像(需先刪除基于該鏡像的所有容器)
bash 運行:
# 先查看鏡像 docker images # 輸出鏡像名、標簽、ID # 示例:REPOSITORY TAG IMAGE ID CREATED SIZE # ubuntu 20.04 f8c79dc85f05 2 hours ago 72.8MB # 刪除鏡像(語法:docker rmi <鏡像名:標簽/鏡像ID>) docker rmi ubuntu:20.04 # 按名稱+標簽刪除 docker rmi f8c79dc85f05 # 按鏡像ID刪除 # 強制刪除被容器引用的鏡像(不推薦,先刪容器) docker rmi -f ubuntu:20.04
五、實戰(zhàn):將自己的代碼運行在 Docker 容器中
掌握了鏡像的選擇和拉取后,接下來進入核心實戰(zhàn)環(huán)節(jié):將自己的代碼打包成鏡像,并在容器中運行。本節(jié)將講解通用流程,并提供多語言示例,確保你能直接落地。
5.1 前提準備:Docker 環(huán)境安裝與驗證
5.1.1 安裝 Docker
Linux(Ubuntu/Debian):
bash運行:
# 更新軟件源 sudo apt update # 安裝依賴 sudo apt install -y ca-certificates curl gnupg lsb-release # 添加 Docker 官方 GPG 密鑰 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 添加 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 # 安裝 Docker sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io # 啟動 Docker 服務 sudo systemctl start docker # 設置開機自啟 sudo systemctl enable docker # 將當前用戶加入 docker 組(避免每次使用 sudo) sudo usermod -aG docker $USER # 重新登錄生效 logout
Windows/macOS:下載 Docker Desktop(https://www.docker.com/products/docker-desktop/),安裝后打開即可,內置 Docker Engine、Docker Compose 等工具。
5.1.2 驗證 Docker 安裝
bash運行:
# 查看 Docker 版本 docker --version # 運行 hello-world 容器(驗證環(huán)境是否正常) docker run hello-world
若輸出 “Hello from Docker!”,說明 Docker 安裝成功。
5.2 通用流程:代碼容器化的核心步驟
無論使用哪種編程語言,代碼容器化的核心流程都包含以下 5 步:
- 整理代碼與依賴;
- 編寫 Dockerfile;
- 構建 Docker 鏡像;
- 啟動容器運行代碼;
- 驗證與調試。
5.2.1 步驟 1:整理代碼與依賴
將代碼和依賴清單放在同一個目錄(稱為 “Docker 上下文目錄”),避免冗余文件(如日志、緩存、編譯產(chǎn)物),減少鏡像體積。
依賴清單的常見形式:
- Python:
requirements.txt; - Node.js:
package.json/package-lock.json; - Java:
pom.xml(Maven)/build.gradle(Gradle); - Go:
go.mod/go.sum。
5.2.2 步驟 2:編寫 Dockerfile(核心)
Dockerfile 是鏡像構建腳本,定義了鏡像的構建步驟。Dockerfile 是無后綴的純文本文件(無 .txt/.sh 等后綴),默認文件名是 Dockerfile(首字母大寫,行業(yè)通用規(guī)范,小寫 dockerfile 也可,但不推薦);若需區(qū)分環(huán)境(如開發(fā) / 生產(chǎn)),也可自定義命名(如 Dockerfile.dev/Dockerfile.prod),構建時需手動指定文件名。
不同系統(tǒng)創(chuàng)建 Dockerfile 的方法
1. Linux/macOS(終端操作)
直接通過終端命令創(chuàng)建空的 Dockerfile,或用編輯器編輯:
bash 運行:
# 1. 創(chuàng)建空的 Dockerfile(最快捷) touch Dockerfile # 2. 編輯 Dockerfile(選其一) vim Dockerfile # 用 vim 編輯(需會 vim 基本操作) nano Dockerfile # 用 nano 編輯(更簡單,新手推薦) code Dockerfile # 用 VS Code 編輯(需安裝 VS Code)
其他操作(自定義Dockerfile文件生成位置):
1. 確定當前所在文件夾
執(zhí)行以下命令,終端會輸出絕對路徑(比如 /home/yourname/project),這是你當前的位置:
bash 運行:
pwd # 打印當前工作目錄(Print Working Directory)
2. 方式 1:指定目錄創(chuàng)建 Dockerfile(推薦,先切換目錄再創(chuàng)建)
步驟:先 cd 到目標文件夾,再創(chuàng)建 Dockerfile,確保文件落在預期位置。
bash 運行:
# 示例:想把Dockerfile創(chuàng)建在 /opt/my-docker-project 目錄下 # 1. 切換到目標目錄(如果目錄不存在,先創(chuàng)建:mkdir -p /opt/my-docker-project) cd /opt/my-docker-project # 2. 確認已切換成功(可選) pwd # 輸出應是 /opt/my-docker-project # 3. 創(chuàng)建空的Dockerfile touch Dockerfile # 4. 驗證文件是否存在(可選) ls # 會看到 Dockerfile 列在輸出中
3. 方式 2:直接指定路徑創(chuàng)建(無需切換目錄)
如果不想 cd 到目標目錄,可直接通過「絕對 / 相對路徑」創(chuàng)建 Dockerfile,比如:
bash 運行:
# 絕對路徑創(chuàng)建:直接指定 Dockerfile 的完整保存路徑 touch /opt/my-docker-project/Dockerfile # 相對路徑創(chuàng)建:基于當前目錄的子目錄(比如當前在 /home/yourname,想創(chuàng)建到 ./docker 子目錄) mkdir -p ./docker # 先創(chuàng)建子目錄(如果不存在) touch ./docker/Dockerfile
4. 驗證 Dockerfile 的位置(避免建錯路徑)
bash 運行:
# 查看文件的絕對路徑(最直觀) realpath Dockerfile # 若在目標目錄,輸出如 /opt/my-docker-project/Dockerfile # 或查看指定路徑下的文件 ls /opt/my-docker-project/ # 看是否有 Dockerfile
2. Windows 系統(tǒng)
Windows 需注意避免自動添加 .txt 后綴,推薦 3 種方式:
方式 1:記事本手動創(chuàng)建
- 右鍵桌面 / 項目目錄 → 新建 → 文本文檔;
- 打開記事本,輸入內容后點擊「文件 → 另存為」;
- 「文件名」填
Dockerfile(無引號),「保存類型」選「所有文件」,「編碼」選UTF-8,點擊保存; - 刪除自動生成的 .txt 文件(若有)。
方式 2:PowerShell/CMD 命令打開終端,進入目標目錄,執(zhí)行:
powershell
# Windows PowerShell New-Item Dockerfile -ItemType File # 或 CMD 命令 type nul > Dockerfile
方式 3:編輯器(VS Code/Notepad++)
- 打開 VS Code → 新建文件(Ctrl+N);
- 直接命名為
Dockerfile(無后綴); - 保存到目標目錄(Ctrl+S)。
Dockerfile內容的核心指令:
| 指令 | 作用 |
|---|---|
| FROM | 指定基礎鏡像(必須是第一行),如 python:3.9-alpine |
| WORKDIR | 設置容器內的工作目錄(避免文件散落) |
| COPY | 把本地文件復制到容器內(格式:COPY 本地路徑 容器路徑) |
| ADD | 類似 COPY,支持解壓壓縮包、下載遠程文件 |
| RUN | 構建鏡像時執(zhí)行的命令(如安裝依賴、編譯代碼) |
| ENV | 設置環(huán)境變量 |
| EXPOSE | 聲明容器暴露的端口(僅提示,不實際映射) |
| CMD | 容器啟動時執(zhí)行的命令(只能有一個,多寫會覆蓋) |
| ENTRYPOINT | 容器啟動的入口命令(與 CMD 配合使用,優(yōu)先級更高) |
| VOLUME | 聲明數(shù)據(jù)卷(用于持久化數(shù)據(jù)) |
| USER | 指定后續(xù)命令的執(zhí)行用戶 |
Dockerfile 編寫原則:
- 盡量減少分層:將多個
RUN命令合并為一個(用&&連接),減少鏡像層數(shù); - 清理緩存:安裝依賴后清理緩存文件(如
apt clean、pip cache purge),減小鏡像體積; - 使用
.dockerignore文件:排除不需要復制到容器的文件(如.git、node_modules、__pycache__)。
5.2.3 步驟 3:構建 Docker 鏡像
使用 docker build 命令構建鏡像,格式:docker build -t 鏡像名:標簽 上下文路徑。
參數(shù)說明:
-t:給鏡像打標簽(方便識別);.:上下文路徑(當前目錄,Docker 會讀取該目錄下的所有文件用于構建);--no-cache:不使用緩存(強制重新構建所有層,用于調試)。
5.2.4 步驟 4:啟動容器運行代碼
使用 docker run 命令啟動容器,核心參數(shù):
-p:端口映射(宿主機端口:容器端口),如-p 8080:5000;-d:后臺運行容器;--name:給容器命名;-v:掛載數(shù)據(jù)卷(本地目錄:容器目錄);--env:設置容器環(huán)境變量;--restart:容器重啟策略(如always,容器崩潰后自動重啟)。
5.2.5 步驟 5:驗證與調試
- 查看容器運行狀態(tài):
docker ps; - 訪問應用:
curl http://localhost:8080; - 查看容器日志:
docker logs 容器名; - 進入容器內部調試:
docker exec -it 容器名 /bin/sh; - 查看容器詳細信息:
docker inspect 容器名。
5.3 多語言實戰(zhàn)示例
5.3.1 示例 1:Python Flask 應用容器化
項目結構(在Linux主機中創(chuàng)建)
my-python-app/ ├── app.py # 業(yè)務代碼 ├── requirements.txt # 依賴清單 ├── Dockerfile # 鏡像構建腳本 └── .dockerignore # 忽略文件
代碼文件
app.py

python文件內容:
from flask import Flask
import os
app = Flask(__name__)
# 讀取環(huán)境變量
APP_NAME = os.getenv("APP_NAME", "Docker Python App")
@app.route('/')
def hello():
return f"Hello from {APP_NAME}! My code is running in Docker container."
if __name__ == '__main__':
# 綁定 0.0.0.0,容器外可訪問
app.run(host='0.0.0.0', port=5000)
requirements.txt
flask==2.3.3

.dockerignore
# Git 相關 .git .gitignore # Python 編譯/虛擬環(huán)境 __pycache__/ *.pyc *.pyo *.pyd venv/ .venv/ # 敏感/本地配置 .env .env.* # 編輯器/系統(tǒng)文件 .idea/ .vscode/ .DS_Store # 日志/臨時文件 *.log tmp/
使用
touch .dockerignore
創(chuàng)建,因為.開頭的文件是隱藏文件,所以創(chuàng)建后是看不到的,可以用:
ls -a

查看文件夾中的所有文件,看到輸出有.dockerignore即可。如果需要向ignore中寫入內容,可以通過文本編輯器vim或nano實現(xiàn):(打開nano,將要寫入的內容粘貼進去,粘貼完成后,按 Ctrl+O 保存,這時底部會出現(xiàn)保存的文件名,再按enter鍵完成保存。接下來按 Ctrl+X 退出 nano。)
nano .dockerignore

Dockerfile
FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt && pip cache purge COPY . . ENV APP_NAME="My Python Docker App" EXPOSE 5000 CMD ["python", "app.py"]
使用:touch Dockerfile構建
【注:雖然后面沒有手動執(zhí)行 docker pull 命令,但鏡像拉取的動作在 docker build 階段被自動觸發(fā)了—— 核心是 Dockerfile 里的 FROM 指令,Docker 會在構建時自動完成 “檢查本地鏡像→缺失則拉取” 的流程?!傅葍r于 docker pull python:3.9-slim」的操作】
構建與運行
bash運行:
# 構建鏡像 docker build -t my-python-app:v1 . # 啟動容器(端口映射 8080:5000,后臺運行) docker run -p 8080:5000 -d --name my-python-container my-python-app:v1 # 驗證 curl http://localhost:8080 # 輸出:Hello from My Python Docker App! My code is running in Docker container. # 查看日志 docker logs my-python-container
如果構建過程中卡住了,可以通過Ctrl+C結束進程,通過:
docker builder prune -f
清理 Docker 構建緩存。如果之前構建過 my-python-app:v1 鏡像,想刪除后重新構建,執(zhí)行:
# 刪除指定鏡像 docker rmi my-python-app:v1 # 若鏡像被容器引用,先刪除容器再刪鏡像: docker rm -f flask-app && docker rmi my-python-app:v1
之后再運行構建代碼,構建完成:

運行容器:
docker run -d -p 5000:5000 --name flask-app my-python-app:v1
在瀏覽器頂部訪問:http://localhost:5000,即可查看到運行結果

如果使用后想停止運行容器,可以使用docker ps查看容器列表
# 僅顯示運行中的容器 docker ps # 或查看所有容器(包括已停止的) docker ps -a
輸出示例(關鍵看 NAMES 列是 flask-app,PORTS 列是 0.0.0.0:5000->5000/tcp):

臨時停止容器(保留容器,可重啟)
如果只是想停止運行,但后續(xù)還想重啟(比如修改代碼后重新啟動),bash 運行:
# 方式1:用容器名稱停止(推薦,直觀) docker stop flask-app # 方式2:用容器ID停止(替換為你的容器ID,比如 abc123456789) docker stop abc123456789

停止后,再次執(zhí)行 docker ps 會看不到該容器,docker ps -a 能看到狀態(tài)變?yōu)?nbsp;Exited (0)。
重啟已停止的容器(臨時停止后想恢復運行)
bash 運行:
# 用名稱重啟 docker start flask-app # 用ID重啟 docker start abc123456789
4. 徹底停止并刪除容器(無需保留)
如果確認后續(xù)不需要該容器,可直接停止并刪除,bash 運行:
# 方式1:先停止再刪除(穩(wěn)妥) docker stop flask-app && docker rm flask-app # 方式2:強制刪除運行中的容器(無需先停止,快捷) docker rm -f flask-app
清理關聯(lián)資源(可選)
刪除鏡像(如果后續(xù)不需要該鏡像)連構建的 my-python-app:v1 鏡像也刪除。bash 運行:
# 先確保容器已刪除,再刪鏡像 docker rmi my-python-app:v1 # 若鏡像被其他容器引用,強制刪除 docker rmi -f my-python-app:v1
5.4 進階優(yōu)化:讓容器運行更實用
5.4.1 數(shù)據(jù)卷(Volume):持久化數(shù)據(jù)
容器內的數(shù)據(jù)默認存儲在可寫層中,容器刪除后數(shù)據(jù)會丟失。數(shù)據(jù)卷用于將容器內的目錄掛載到宿主機或命名卷,實現(xiàn)數(shù)據(jù)持久化。
綁定掛載(本地目錄 → 容器目錄)
bash運行:
# 將本地 ./data 目錄掛載到容器 /app/data 目錄 docker run -p 8080:5000 -v $(pwd)/data:/app/data my-python-app:v1
命名卷(Docker 管理的卷)
bash運行:
# 創(chuàng)建命名卷 docker volume create my-data # 掛載命名卷到容器 docker run -p 8080:5000 -v my-data:/app/data my-python-app:v1 # 查看卷信息 docker volume inspect my-data
5.4.2 Docker Compose:多容器管理
當應用依賴多個服務(如 MySQL、Redis)時,使用 Docker Compose 可一鍵啟動所有服務。
示例 docker-compose.yml
yaml
version: '3.8'
services:
# 應用服務
app:
build: .
ports:
- "8080:5000"
environment:
- APP_NAME=My Python Docker App
- REDIS_HOST=redis
- MYSQL_HOST=mysql
- MYSQL_USER=root
- MYSQL_PASSWORD=123456
- MYSQL_DB=test
volumes:
- ./data:/app/data
depends_on:
- redis
- mysql
restart: always
# Redis 服務
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
restart: always
# MySQL 服務
mysql:
image: mysql:5.7
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=test
volumes:
- mysql-data:/var/lib/mysql
restart: always
# 命名卷
volumes:
redis-data:
mysql-data:
啟動 / 停止服務
bash運行:
# 啟動所有服務(后臺運行) docker-compose up -d # 查看服務狀態(tài) docker-compose ps # 查看日志 docker-compose logs app # 停止服務 docker-compose down # 停止服務并刪除數(shù)據(jù)卷 docker-compose down -v
5.4.3 熱重載(開發(fā)環(huán)境)
開發(fā)環(huán)境中,修改代碼后希望容器自動重啟,無需重新構建鏡像。
Python 示例(使用 flask-reload)
修改 Dockerfile 的啟動命令:
CMD ["python", "-m", "flask", "run", "--host=0.0.0.0", "--port=5000", "--reload"]
啟動容器時掛載代碼目錄:
bash運行:
docker run -p 8080:5000 -v $(pwd):/app my-python-app:v1
修改本地 app.py 后,F(xiàn)lask 會自動重啟,無需重啟容器。
5.5 調試與排錯:容器運行常見問題解決
5.5.1 容器啟動后訪問不通
- 檢查端口映射:確認
docker run命令使用了-p參數(shù),且宿主機端口未被占用; - 檢查代碼綁定地址:確保服務綁定
0.0.0.0,而非127.0.0.1(容器內 127.0.0.1 僅容器自身可訪問); - 檢查防火墻:宿主機防火墻是否放行映射的端口;
- 查看容器日志:
docker logs 容器名,排查代碼報錯。
5.5.2 依賴安裝失敗
- 檢查網(wǎng)絡:容器是否能訪問外網(wǎng)(可進入容器
ping baidu.com測試); - 使用國內源:在 Dockerfile 中配置國內源(如 pip、npm、maven 國內源);
- 檢查依賴版本:依賴版本與基礎鏡像不兼容(如 Python 3.9 安裝不支持的包版本)。
5.5.3 鏡像體積過大
- 使用多階段構建:僅保留運行所需文件;
- 清理緩存:安裝依賴后清理緩存(如
apt clean、pip cache purge); - 合并
RUN命令:減少鏡像層數(shù); - 使用輕量化基礎鏡像(如 alpine 版本)。
5.5.4 容器崩潰自動重啟
- 設置重啟策略:
docker run --restart=always; - 查看崩潰原因:
docker logs 容器名,排查代碼或依賴問題; - 限制容器資源:
docker run --memory=512m --cpus=1,避免資源耗盡。
六、總結
Docker 作為容器化技術的標桿,已成為現(xiàn)代軟件開發(fā)和運維的必備工具。其核心價值在于解決了環(huán)境一致性、資源隔離、快速部署等核心痛點,為微服務架構、CI/CD 流水線、云原生應用提供了堅實的基礎。本文從 Docker 的定義、使用價值、核心概念、鏡像選擇、代碼容器化實戰(zhàn)等維度,全面講解了 Docker 的核心知識。
總結核心要點:
- Docker 是輕量級的容器化平臺,核心是 “一次構建,到處運行”;
- Docker 容器是宿主機上的受限制進程,基于鏡像運行,鏡像為只讀模板;
- 選擇鏡像時應優(yōu)先官方、輕量化、指定版本的鏡像;
- 代碼容器化的核心是編寫 Dockerfile,通過
docker build構建鏡像,docker run啟動容器; - 結合 Docker Compose 可輕松管理多服務依賴,提升部署效率。
未來,Docker 將繼續(xù)與 Kubernetes(k8s) 深度融合,成為云原生技術的核心組件。掌握 Docker 不僅能提升開發(fā) / 部署效率,更是進入云原生領域的必備技能。
附錄:Docker 常用命令速查表
鏡像管理
| 命令 | 作用 |
|---|---|
| docker search <name> | 搜索鏡像 |
| docker pull <name>:<tag> | 拉取鏡像 |
| docker images | 查看本地鏡像 |
| docker rmi <name>:<tag> | 刪除鏡像 |
| docker tag <old> <new> | 重命名鏡像 |
| docker history <name> | 查看鏡像構建歷史 |
| docker image prune -a | 刪除未使用的鏡像 |
容器管理
| 命令 | 作用 |
|---|---|
| docker run <options> <image> | 啟動容器 |
| docker ps | 查看運行中的容器 |
| docker ps -a | 查看所有容器 |
| docker stop <name/id> | 停止容器 |
| docker start <name/id> | 啟動已停止的容器 |
| docker restart <name/id> | 重啟容器 |
| docker rm <name/id> | 刪除容器 |
| docker exec -it <name/id> sh | 進入容器內部 |
| docker logs <name/id> | 查看容器日志 |
| docker inspect <name/id> | 查看容器 / 鏡像詳細信息 |
| docker container prune | 刪除已停止的容器 |
Docker Compose
| 命令 | 作用 |
|---|---|
| docker-compose up | 啟動服務 |
| docker-compose up -d | 后臺啟動服務 |
| docker-compose down | 停止并刪除服務 |
| docker-compose ps | 查看服務狀態(tài) |
| docker-compose logs <service> | 查看服務日志 |
| docker-compose build | 構建服務鏡像 |
| docker-compose restart <service> | 重啟服務 |
最后
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Docker數(shù)據(jù)卷的核心原理與管理邏輯解讀
Docker數(shù)據(jù)卷實現(xiàn)容器與宿主機的數(shù)據(jù)持久化,分為綁定掛載(手動指定路徑)和管理卷(自動管理),前者適合開發(fā)環(huán)境,后者適用于生產(chǎn)環(huán)境,還支持多容器共享、備份遷移及清理,保障數(shù)據(jù)安全與資源高效利用2025-08-08
skywalking容器化部署docker鏡像構建k8s從測試到可用
這篇文章主要為大家介紹了skywalking容器化部署docker鏡像構建k8s從測試到可用的構建部署過程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步2022-03-03
docker部署管理工具portainer-ce的實現(xiàn)
Portainer是一個可視化的容器鏡像的圖形管理工具,利用Portainer可以輕松構建,管理和維護Docker環(huán)境,本文主要介紹了docker部署管理工具portainer-ce的實現(xiàn),感興趣的可以了解一下2023-08-08

