目錄
一、先分清:Docker、Tomcat、k8s 到底是 “干啥的”?
二、它們的 “合作關系”:從 Java 項目到集群部署的全流程
三、實際應用場景:什么時候該用誰?
1. 單獨使用場景
2. 組合使用場景(最常見)
四、簡單實操示例:手把手部署一個 Java 項目
1. 步驟 1:用 Docker 打包 Tomcat 鏡像
2. 步驟 2:用 k8s 部署這個 Docker 鏡像
五、常用使用方法:核心命令速查
1. Docker 核心命令
2. Tomcat 核心操作
3. k8s 核心命令
六、踩坑指南:常見問題 + 解決方法
1. Docker+Tomcat:訪問項目 404
2. k8s:Pod 一直處于 Pending 狀態
3. Tomcat:啟動報錯 “Address already in use”
七、段子解疑:抽象概念秒懂
1. 用 “小區物業” 理解 k8s 的 “編排”
2. 用 “外賣” 理解 Docker+Tomcat 的關系
3. 用 “奶茶店” 理解 k8s 的 “副本”
八、專業總結
大家好,我是做云原生運維的小大..剛入行時,我曾對著服務器上的 Docker 容器、Tomcat 進程和 k8s 控制臺發懵:“為啥部署個 Java 項目,一會兒打包 Docker 鏡像,一會兒啟動 Tomcat,最后還要 k8s 來‘管閑事’?” 后來踩了無數坑才明白,這三者不是 “互斥選項”,而是從 “單機部署” 到 “集群運維” 的協同工具鏈。今天咱們就從定位、聯系、實操到踩坑,一次性講透,還會用段子幫你啃下抽象難點~
一、先分清:Docker、Tomcat、k8s 到底是 “干啥的”?
很多人混淆它們,核心是沒搞懂各自的 “核心定位”—— 它們解決的是完全不同的問題,咱們用表格一目了然:
工具 | 核心定位 | 解決的核心痛點 | 角色類比 |
---|---|---|---|
Docker | 容器引擎(打包工具) | 開發 / 測試 / 生產環境不一致(“我這能跑啊”) | 外賣打包盒 |
Tomcat | Java Web 服務器(運行環境) | Java 項目無法直接運行,需依賴 Web 容器 | 外賣里的 “米飯” |
k8s | 容器編排平臺(管理工具) | 多容器集群的運維(啟停 / 擴容 / 高可用) | 小區物業 |
重點標顯:
- Docker 不負責 “運行項目”,只負責 “把項目和運行環境打包成容器”;
- Tomcat 不負責 “環境一致性”,只負責 “讓 Java 項目在容器里跑起來”;
- k8s 不負責 “打包或運行”,只負責 “管理一堆容器的生命周期”。
二、它們的 “合作關系”:從 Java 項目到集群部署的全流程
三者不是 “二選一”,而是 “流水線協作”,以部署一個 Spring MVC 項目為例,完整鏈路是這樣的:
- 開發端:寫好 Java 項目,打成 War 包(比如
my-project.war
); - Docker 打包:寫一個 Dockerfile,把 “Tomcat 鏡像” 和 “War 包” 一起打包成新鏡像(比如
my-tomcat:v1
)—— 相當于 “用外賣盒(Docker)裝起米飯(Tomcat)和菜(Java 項目)”; - k8s 部署:用 k8s 的 Deployment 配置,指定 “啟動 3 個
my-tomcat:v1
容器副本”,并通過 Service 暴露訪問端口 —— 相當于 “物業(k8s)安排 3 個‘打包好的外賣’(容器)上架,還貼上門牌號(Service)方便別人找到”; - 用戶訪問:用戶通過 k8s 的 Service 地址訪問,請求會被分發到任意一個容器上,實現高可用。
重點標顯:
- 沒有 Docker:Tomcat 和項目在不同環境可能 “水土不服”(比如開發端 Tomcat 8,生產端 Tomcat 9);
- 沒有 Tomcat:Docker 容器里只有項目文件,Java 項目 “沒地方跑”;
- 沒有 k8s:幾十上百個 Docker 容器需要手動啟停、監控,運維能累到 “脫發”。
三、實際應用場景:什么時候該用誰?
1. 單獨使用場景
- Docker:個人開發 / 小型項目的 “環境一致性” 需求。比如你本地開發用 Ubuntu,測試環境是 CentOS,用 Docker 打包后,測試端直接運行鏡像,不用再裝依賴;
- Tomcat:單機部署 Java Web 項目。比如公司內部的 OA 系統,用戶少、訪問量低,直接在服務器上裝 Tomcat,把 War 包扔到
webapps
目錄就能跑; - k8s:微服務集群 / 高可用場景。比如電商的訂單系統、支付系統,需要幾十上百個容器,還要應對 “雙 11” 的流量峰值,k8s 能自動擴容、故障恢復。
2. 組合使用場景(最常見)
- Docker + Tomcat:中小型 Java 項目的 “跨環境部署”。比如把 Tomcat 和項目打包成鏡像,部署到不同服務器,不用再手動配置 Tomcat;
- Docker + Tomcat + k8s:大型微服務的 “集群運維”。比如某互聯網公司的用戶服務,用 k8s 部署 10 個 Tomcat 容器副本,通過 Service 負載均衡,當某個容器掛了,k8s 自動重啟,流量無縫切換。
四、簡單實操示例:手把手部署一個 Java 項目
咱們以 “用 Docker 打包 Tomcat+Java 項目,再用 k8s 管理” 為例,走一遍核心步驟(假設你已有 Java War 包my-project.war
)。
1. 步驟 1:用 Docker 打包 Tomcat 鏡像
創建Dockerfile
(核心配置):
dockerfile
# 基礎鏡像:用官方Tomcat 8(避免環境差異)
FROM tomcat:8-jdk8# 重點:刪除Tomcat默認的ROOT項目(避免沖突)
RUN rm -rf /usr/local/tomcat/webapps/ROOT# 把本地的War包復制到Tomcat的webapps/ROOT(這樣訪問時不用加項目名)
COPY my-project.war /usr/local/tomcat/webapps/ROOT.war# 暴露Tomcat默認端口8080
EXPOSE 8080# 啟動Tomcat(用官方鏡像的啟動腳本)
CMD ["catalina.sh", "run"]
然后構建鏡像:
# 重點命令:-t 給鏡像起名(my-tomcat)+ 版本(v1),. 表示當前目錄找Dockerfile
docker build -t my-tomcat:v1 .
本地測試鏡像是否能跑:
docker run -d -p 8080:8080 --name test-tomcat my-tomcat:v1
# 訪問 http://localhost:8080,能看到項目頁面說明成功
2. 步驟 2:用 k8s 部署這個 Docker 鏡像
創建 k8s 部署配置文件tomcat-deploy.yaml
:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: tomcat-deployment # 部署名
spec:replicas: 3 # 重點:啟動3個副本(高可用)selector:matchLabels:app: tomcattemplate:metadata:labels:app: tomcatspec:containers:- name: tomcat-containerimage: my-tomcat:v1 # 用剛才構建的Docker鏡像ports:- containerPort: 8080 # 容器內部端口resources: # 可選:限制資源(避免占用太多)limits:cpu: "1"memory: "1Gi"requests:cpu: "0.5"memory: "512Mi"
---
# 重點:創建Service,讓外部能訪問容器(相當于“門牌號”)
apiVersion: v1
kind: Service
metadata:name: tomcat-service
spec:type: NodePort # 適合測試:暴露節點端口selector:app: tomcat # 和Deployment的label對應ports:- port: 8080 # Service內部端口targetPort: 8080 # 容器端口nodePort: 30080 # 外部訪問端口(30000-32767之間)
然后部署到 k8s:
# 重點命令:應用配置文件
kubectl apply -f tomcat-deploy.yaml# 查看部署狀態
kubectl get pods # 能看到3個Running的pod
kubectl get service tomcat-service # 能看到暴露的節點端口30080
外部訪問:http://k8s-node-ip:30080
,就能訪問到 Java 項目了。
五、常用使用方法:核心命令速查
1. Docker 核心命令
功能 | 命令示例 | 重點說明 |
---|---|---|
構建鏡像 | docker build -t 鏡像名:版本 . | 末尾的 “.” 不能漏 |
運行容器 | docker run -d -p 宿主端口:容器端口 鏡像名 | -d 表示后臺運行 |
查看運行中的容器 | docker ps | 加 -a 看所有容器 |
查看容器日志 | docker logs -f 容器名/ID | -f 實時跟蹤日志 |
停止容器 | docker stop 容器名/ID | 強制停止用 docker kill |
2. Tomcat 核心操作
功能 | 操作方法 | 重點說明 |
---|---|---|
啟動(Linux) | ./bin/startup.sh | 需先給腳本執行權限(chmod +x) |
停止(Linux) | ./bin/shutdown.sh | 強制停止用 kill -9 進程號 |
修改端口 | 編輯?conf/server.xml ?中的?<Connector port="8080"> | 避免端口沖突 |
部署項目 | 把 War 包放到?webapps ?目錄 | 重啟 Tomcat 生效 |
3. k8s 核心命令
功能 | 命令示例 | 重點說明 |
---|---|---|
應用配置文件 | kubectl apply -f 文件名.yaml | 新增 / 更新資源都能用 |
查看 Pod 狀態 | kubectl get pods | 加 -o wide 看節點信息 |
查看 Pod 日志 | kubectl logs -f pod名 | 加 -c 容器名(多容器時) |
進入 Pod 內部 | kubectl exec -it pod名 -- /bin/bash | 調試用 |
擴縮容副本數 | kubectl scale deployment 部署名 --replicas=5 | 快速調整副本數量 |
六、踩坑指南:常見問題 + 解決方法
1. Docker+Tomcat:訪問項目 404
- 問題現象:Docker 容器啟動成功,但訪問
http://localhost:8080
報 404; - 核心原因:War 包沒放到 Tomcat 的正確路徑,或沒重命名為
ROOT.war
; - 解決步驟:
- 進入容器查看路徑:
docker exec -it 容器名 ls /usr/local/tomcat/webapps
; - 確認 War 包是否存在,若不存在,檢查 Dockerfile 的
COPY
路徑是否正確; - 若存在但不是
ROOT.war
,修改 Dockerfile 為COPY my-project.war /usr/local/tomcat/webapps/ROOT.war
,重新構建鏡像。
- 進入容器查看路徑:
2. k8s:Pod 一直處于 Pending 狀態
- 問題現象:
kubectl get pods
顯示 Pod 狀態為 Pending,事件里提示 “no nodes available to schedule pods”; - 核心原因:k8s 節點資源不足(CPU / 內存),或節點有污點(Taint);
- 解決步驟:
- 查看事件詳情:
kubectl describe pod pod名
,找到 “Events” 部分; - 若提示 “Insufficient cpu”,修改
tomcat-deploy.yaml
的resources.limits.cpu
為更小值(比如 0.5); - 若提示 “Taint toleration not found”,給 Pod 添加污點容忍(Toleration),或移除節點污點。
- 查看事件詳情:
3. Tomcat:啟動報錯 “Address already in use”
- 問題現象:Tomcat 啟動時提示 “8080 端口被占用”;
- 核心原因:服務器上其他進程占用了 8080 端口;
- 解決步驟:
- 查找占用端口的進程:
netstat -tulpn | grep 8080
(Linux); - 若進程可停止,用
kill -9 進程號
停止; - 若進程不能停,修改 Tomcat 的
conf/server.xml
,把<Connector port="8080">
改成其他端口(比如 8081),重啟 Tomcat。
- 查找占用端口的進程:
七、段子解疑:抽象概念秒懂
1. 用 “小區物業” 理解 k8s 的 “編排”
k8s 的 “編排” 到底是啥?其實就是 “小區物業的日常”:
- Docker 容器 = 小區里的住戶;
- k8s = 物業;
- 住戶(容器)家里水管爆了(掛了),物業(k8s)不用你打電話,直接派維修員換個新住戶(重啟副本);
- 小區人多了(容器多了),物業分單元管理(命名空間 Namespace),避免混亂;
- 外人要找住戶(外部訪問),物業給個門牌號(Service),不用記住戶的具體房間號(Pod IP);
- 住戶要用電(資源),物業規定每戶最多用多少(resources.limits),避免有人占太多導致其他人沒電用。
2. 用 “外賣” 理解 Docker+Tomcat 的關系
Docker 和 Tomcat 的配合,就像 “外賣套餐”:
- Docker = 外賣盒;
- Tomcat = 外賣里的米飯;
- 你的 Java 項目 = 外賣里的菜;
- 沒有外賣盒(Docker):米飯(Tomcat)和菜(項目)容易撒(環境不一致),比如你在公司點的菜,帶回家就涼了(依賴缺失);
- 沒有米飯(Tomcat):菜(項目)沒法吃(Java 項目不能直接運行,需要 Web 容器解析);
- 外賣盒里裝著米飯和菜,不管你在公司、家里還是咖啡店(不同服務器),打開就能吃(一致部署)。
3. 用 “奶茶店” 理解 k8s 的 “副本”
k8s 的 “副本(Replicas)”,就是奶茶店的 “備用珍珠”:
- 你點一杯奶茶(用戶發一個請求),需要加珍珠(容器處理請求);
- 如果珍珠不夠(容器數量少),后面的人就要等(請求排隊),店員趕緊加備用珍珠(k8s 擴容副本);
- 如果有一顆珍珠壞了(容器掛了),店員直接換一顆新的(k8s 重啟副本),你完全沒感覺,繼續喝奶茶;
- 奶茶店打烊(服務下線),店員把所有珍珠收走(k8s 刪除 Pod),下次開門再拿新的(重新部署)。
八、專業總結
Docker、Tomcat 與 k8s 的關系,本質是云原生架構下 “從單機到集群” 的工具協同鏈:
- Docker是基礎:解決了 “環境一致性” 問題,讓 “一次打包,到處運行” 成為可能,是容器化的基石;
- Tomcat是核心:作為 Java 生態的主流 Web 服務器,是 Java 項目容器化的 “必需運行環境”,沒有它,Java 項目無法在 Docker 容器中生效;
- k8s是升華:基于 Docker 實現了 “容器集群的自動化管理”,解決了高可用、彈性擴容、故障自愈等運維痛點,讓微服務架構落地成為可能。
三者并非替代關系,而是 “打包→運行→管理” 的遞進:小項目可用 Docker+Tomcat 快速部署,大項目則需 k8s 實現集群化運維。理解它們的定位和協同邏輯,才能在云原生路上少走彎路~
如果大家在實操中遇到其他問題,歡迎在評論區留言,咱們一起討論解決!