Docker+Tomcat部署实战:从环境隔离到生产级容器化应用
1. 项目概述:为什么Docker+Tomcat是部署的“黄金搭档”?
干了这么多年开发和运维,我见过太多项目在部署环节“翻车”。明明本地测试跑得好好的,一上服务器就各种环境问题、端口冲突、依赖缺失。后来Docker火了,我算是彻底被它“驯服”了。今天要聊的,就是把Docker和咱们的老朋友Tomcat绑在一起,搞出一套标准化、可移植的Web应用部署方案。这可不是简单的命令堆砌,而是从思路到实操,帮你把部署这个事儿彻底捋顺。
简单说,Docker是一个容器化平台,它能把你的应用及其所有依赖(比如特定的JDK版本、库文件、环境变量)打包成一个独立的“集装箱”,也就是镜像。这个镜像在任何安装了Docker的机器上,都能以完全一致的方式运行起来,这就是容器。而Tomcat,作为最经典的Java Web服务器,是我们打包的核心目标。用Docker部署Tomcat,意味着你再也不用在服务器上手动安装JDK、下载Tomcat压缩包、配置CATALINA_HOME、担心多个项目环境互相污染了。你只需要一个Docker命令,一个干净、隔离、配置好的Tomcat环境瞬间就绪。无论是单机测试,还是集群化部署,这套组合拳都能让你游刃有余。
这篇文章适合所有被部署问题困扰的Java开发者、运维新手,以及想体验现代化部署流程的团队。我会从Docker最基础的安装、配置讲起,一直深入到如何定制Tomcat镜像、部署你的Web项目,并分享一堆我踩过坑才总结出来的实操细节。咱们不玩虚的,直接上干货。
2. Docker核心概念与安装避坑指南
在动手之前,得先搞清楚我们在玩什么。Docker有三个核心概念:镜像(Image)、容器(Container)和仓库(Registry)。你可以把镜像理解成软件的安装包(比如一个.exe文件),它包含了运行所需的一切。容器则是这个安装包运行起来的实例(就像你双击.exe后启动的程序)。一个镜像可以创建无数个容器,它们相互隔离。仓库就是存放镜像的地方,Docker官方仓库叫Docker Hub,就像手机的应用商店。
2.1 在不同操作系统上安装Docker
Docker的安装因操作系统而异,Windows和macOS用户通常使用Docker Desktop,而Linux用户则直接安装Docker Engine。这里面的坑,主要集中在Windows和macOS上。
对于Linux(以Ubuntu为例),安装是最顺畅的。通过官方脚本或包管理器即可。
# 卸载旧版本(如果有) sudo apt-get remove docker docker-engine docker.io containerd runc # 更新包索引并安装依赖 sudo apt-get update sudo apt-get install 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 # 设置稳定版仓库 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 Engine sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin # 启动Docker并设置开机自启 sudo systemctl start docker sudo systemctl enable docker # 将当前用户加入docker组,避免每次都用sudo(操作后需退出终端重新登录) sudo usermod -aG docker $USER对于Windows/macOS用户,需要安装Docker Desktop。这是最容易出问题的地方,尤其是Windows。
注意:Docker Desktop在Windows上依赖于Windows的Hyper-V或WSL 2(Windows Subsystem for Linux 2)来提供Linux内核环境。如果你的系统不支持虚拟化,或者虚拟化功能未开启,安装就会失败。
2.2 破解“Virtualization Support Not Detected”致命错误
这是Windows用户安装Docker Desktop时最高频的报错:“Docker Desktop failed to start because virtualisation support wasn’t detected”。别慌,按以下步骤排查,99%的问题都能解决。
第一步:确认CPU和BIOS支持虚拟化。这几乎是所有问题的根源。虚拟化技术(Intel的VT-x或AMD的AMD-V)必须在CPU硬件层面支持,并在主板的BIOS/UEFI设置中开启。
- 任务管理器检查:重启电脑,开机时狂按
Delete或F2等键进入BIOS/UEFI设置界面(不同主板按键不同)。找到类似“Advanced”(高级) -> “CPU Configuration”(CPU配置)或“Security”(安全)的选项。寻找“Intel Virtualization Technology”(Intel VT-x)或“AMD SVM Mode”,将其状态从“Disabled”改为“Enabled”。保存并退出。 - 系统内确认:进入Windows后,打开“任务管理器”(Ctrl+Shift+Esc),切换到“性能”标签页,点击“CPU”。在右下角查看“虚拟化”是否显示为“已启用”。
第二步:关闭冲突的虚拟化程序。如果你电脑上安装了其他虚拟机软件,如VMware Workstation、VirtualBox,或者某些安卓模拟器(如雷电模拟器),它们可能会独占虚拟化功能,导致Docker Desktop无法启动。
- 方案A(推荐):彻底卸载这些冲突的软件。对于开发测试,Docker容器通常足够。
- 方案B:如果必须保留,可以尝试在Windows“启用或关闭Windows功能”中,关闭“Hyper-V”和“Windows虚拟机监控程序平台”,然后使用VirtualBox等。但这样你就无法使用Docker Desktop了,可以考虑在VirtualBox里安装一个Linux虚拟机,然后在Linux里安装Docker Engine。
第三步:启用Windows相关功能。确保以下Windows功能被开启:
- 搜索“启用或关闭Windows功能”,打开对话框。
- 勾选“Hyper-V”(包含Hyper-V管理工具和平台)、“Windows虚拟机监控程序平台”、“Windows Subsystem for Linux”。
- 点击确定,重启电脑。
第四步:关于WSL 2。Docker Desktop默认使用WSL 2作为后端,比传统的Hyper-V更轻量、性能更好。
- 确保已安装WSL 2。在PowerShell(管理员身份)中运行:
wsl --install。这会安装默认的Linux发行版(通常是Ubuntu)并设置WSL 2。 - 设置WSL 2为默认版本:
wsl --set-default-version 2。 - 在Docker Desktop设置中,选择“Use WSL 2 based engine”。
完成以上步骤后,再次启动Docker Desktop,通常就能看到那只快乐的小鲸鱼了。安装成功后,在命令行输入docker --version和docker run hello-world来验证安装。如果能看到版本信息和一个欢迎消息,说明你的Docker世界已经畅通无阻。
3. Docker基础命令与镜像加速配置
安装只是第一步,接下来要学习如何“驾驶”这艘船。Docker命令是与之交互的核心。同时,直接从Docker Hub拉取镜像可能会非常慢,配置国内镜像加速器是必做操作。
3.1 你必须掌握的Docker核心命令
命令不用死记硬背,但几个最常用的必须形成肌肉记忆。它们主要围绕镜像和容器的生命周期。
镜像相关命令:
docker pull [镜像名]:[标签]:从仓库拉取镜像。例如docker pull tomcat:9.0。不指定标签则默认为latest。docker images:列出本地所有镜像。查看镜像ID、仓库名、标签、大小等信息。docker rmi [镜像ID或镜像名]:删除本地镜像。如果镜像有容器正在使用,需要先停止并删除容器。docker build -t [自定义镜像名]:[标签] .:根据当前目录的Dockerfile构建自定义镜像。这个点.代表构建上下文路径。
容器相关命令(这是重中之重):
docker run [选项] [镜像名]:从镜像创建并启动一个新容器。这是最复杂的命令,常用选项有:-d:后台运行(守护进程模式)。-p [宿主机端口]:[容器端口]:端口映射,将容器内端口暴露到宿主机。例如-p 8080:8080。-v [宿主机目录]:[容器目录]:数据卷挂载,实现宿主机和容器间数据持久化和共享。--name [容器名]:为容器指定一个自定义名称,便于管理。-e [环境变量名]=[值]:设置容器内的环境变量。-it:交互模式运行,通常与/bin/bash结合,进入容器内部。例如docker run -it ubuntu /bin/bash。
docker ps:列出正在运行的容器。加-a选项列出所有容器(包括已停止的)。docker stop [容器ID或容器名]:停止一个运行中的容器。docker start [容器ID或容器名]:启动一个已停止的容器。docker restart [容器ID或容器名]:重启容器。docker rm [容器ID或容器名]:删除一个已停止的容器。加-f可以强制删除运行中的容器。docker logs [容器ID或容器名]:查看容器的日志输出,排查问题必备。docker exec -it [容器ID或容器名] /bin/bash:进入一个正在运行的容器内部,就像SSH进去一样,进行调试或操作。
一个经典组合拳示例:我想运行一个Tomcat,并且把我的项目myapp.war放进去。
- 拉取镜像:
docker pull tomcat:9.0 - 运行容器:
docker run -d --name my-tomcat -p 8888:8080 -v /home/myapp:/usr/local/tomcat/webapps tomcat:9.0-d后台运行。--name my-tomcat给容器起名叫my-tomcat。-p 8888:8080把容器内的8080端口映射到宿主机的8888端口,这样我访问http://宿主机IP:8888就能看到Tomcat了。-v /home/myapp:/usr/local/tomcat/webapps把宿主机的/home/myapp目录挂载到容器的webapps目录。我只需要把myapp.war扔进宿主机的/home/myapp,它就会自动出现在Tomcat的发布目录。
- 查看是否运行:
docker ps - 查看日志:
docker logs -f my-tomcat(-f表示持续跟踪输出) - 进入容器看看:
docker exec -it my-tomcat /bin/bash
3.2 配置国内镜像加速器,拉取镜像飞起来
默认的Docker Hub在国外,拉取镜像速度堪忧。我们必须配置国内镜像加速器。国内常用的有阿里云、腾讯云、网易云、中科大等提供的镜像服务。
Linux系统配置方法(以阿里云为例):
- 注册阿里云账号,进入“容器镜像服务” -> “镜像工具” -> “镜像加速器”,你会得到一个专属的加速器地址,格式如
https://xxxx.mirror.aliyuncs.com。 - 编辑Docker的守护进程配置文件(如果不存在则创建):
请将sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"] } EOFhttps://xxxx.mirror.aliyuncs.com替换成你从阿里云控制台复制的地址。你可以配置多个镜像源,用逗号隔开。 - 重新加载配置并重启Docker服务:
sudo systemctl daemon-reload sudo systemctl restart docker - 验证是否生效:
docker info。在输出信息中查找Registry Mirrors,如果看到你配置的地址,说明成功了。
Docker Desktop(Windows/macOS)配置方法:更加简单。右键点击系统托盘中的Docker鲸鱼图标,选择“Settings”(设置) -> “Docker Engine”。在打开的JSON配置窗口中,直接在registry-mirrors数组中添加你的加速器地址。然后点击“Apply & Restart”。
配置完成后,你再执行docker pull tomcat,速度会有质的飞跃。这是提升Docker使用体验非常关键的一步。
4. 从零开始:使用官方镜像运行Tomcat
理论准备就绪,现在开始实战。我们从最简单的开始:使用Docker官方提供的Tomcat镜像,快速启动一个Tomcat服务器。
4.1 拉取与运行官方Tomcat镜像
Docker Hub上官方维护了Tomcat镜像,标签对应了不同的Tomcat和JDK版本组合,例如tomcat:9.0、tomcat:9.0-jdk11、tomcat:10.0-jdk17等。选择时,务必与你的项目所需的JDK版本匹配。
# 拉取Tomcat 9.0 官方镜像(默认包含兼容的JDK) docker pull tomcat:9.0 # 运行一个最简单的Tomcat容器 docker run -d --name my-first-tomcat -p 8080:8080 tomcat:9.0执行后,访问http://localhost:8080,你应该能看到Tomcat的默认主页。恭喜,你的第一个Docker化Tomcat已经跑起来了!但你会发现,官方镜像的默认webapps目录下只有ROOT、docs、examples等,没有manager应用(用于Web管理界面)。这是因为安全考虑,最新镜像默认移除了manager。如果你需要,可以自己添加。
4.2 深入容器内部:目录结构与项目部署
理解Tomcat容器内部的结构,是灵活部署的基础。我们可以使用docker exec命令进入容器一探究竟。
# 进入正在运行的容器 docker exec -it my-first-tomcat /bin/bash # 进入后,你就在容器的Linux环境里了。查看Tomcat目录 ls -la /usr/local/tomcat/关键目录说明:
/usr/local/tomcat/webapps/:这是Web应用的部署目录。你把WAR包放在这里,或者创建一个包含WEB-INF的文件夹,Tomcat会自动部署(解压WAR或直接使用文件夹)。/usr/local/tomcat/conf/:配置文件目录,包含server.xml、web.xml等。/usr/local/tomcat/logs/:日志文件目录,catalina.out是主要输出日志。/usr/local/tomcat/work/:Tomcat的工作目录,存放JSP编译后的Servlet等。
那么,如何部署我们自己的项目呢?有三种主流方式:
方式一:直接复制WAR包到容器内(不推荐用于生产)
# 假设你的WAR包叫myapp.war,在宿主机当前目录 # 先复制到容器内 docker cp myapp.war my-first-tomcat:/usr/local/tomcat/webapps/ # 然后重启容器(或者Tomcat会自动热部署,但重启更稳妥) docker restart my-first-tomcat这种方式简单,但项目文件存在于容器内部。如果容器被删除,你的项目也就没了。它违背了容器“无状态”的最佳实践。
方式二:使用数据卷挂载(推荐)这是更优雅的方式,将宿主机的目录挂载到容器的webapps目录。
# 停止并删除旧容器 docker stop my-first-tomcat && docker rm my-first-tomcat # 创建宿主机目录存放项目 mkdir -p /home/docker-data/tomcat-webapps # 将你的myapp.war放入 /home/docker-data/tomcat-webapps/ # 运行新容器,并挂载目录 docker run -d --name my-tomcat -p 8080:8080 \ -v /home/docker-data/tomcat-webapps:/usr/local/tomcat/webapps \ tomcat:9.0现在,你只需要管理宿主机/home/docker-data/tomcat-webapps/目录下的文件。放入WAR包,Tomcat会自动部署;修改文件,容器内实时生效。数据持久化在宿主机,容器可以随意重建。
方式三:构建自定义镜像(最规范,适合CI/CD)将项目WAR包直接打包进镜像,使得镜像本身就是一个完整的、可交付的应用单元。这需要编写Dockerfile,我们将在下一章详细讲解。
5. 进阶实战:定制专属Tomcat镜像与优化配置
直接使用官方镜像往往不能满足生产需求。我们可能需要修改默认配置、调整JVM参数、预装一些工具,或者将应用直接打包进去。这时,就需要通过Dockerfile来构建自定义镜像。
5.1 编写Dockerfile:打造你的专属Tomcat
Dockerfile是一个文本文件,包含了一系列构建镜像的指令。我们以一个典型的场景为例:基于官方Tomcat镜像,部署一个特定的WAR包,并修改一些默认配置。
首先,准备一个项目目录,里面包含你的WAR包(例如my-application.war)和一个Dockerfile文件。
# Dockerfile # 第一阶段:使用官方Tomcat镜像作为基础 FROM tomcat:9.0-jdk11-openjdk-slim AS builder # 维护者信息(可选) LABEL maintainer="your-email@example.com" # 删除Tomcat默认的webapps下的所有内容(按需,这里我们保留默认,只添加自己的) # RUN rm -rf /usr/local/tomcat/webapps/* # 将本地的WAR包复制到容器的webapps目录下,并重命名为ROOT.war(这样访问根路径就是你的应用) COPY my-application.war /usr/local/tomcat/webapps/ROOT.war # 如果需要复制自定义的配置文件,比如server.xml, context.xml等 # COPY conf/server.xml /usr/local/tomcat/conf/ # COPY conf/context.xml /usr/local/tomcat/conf/ # 设置JVM环境变量(例如调整内存,非常重要!) ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC" # 暴露Tomcat默认端口 EXPOSE 8080 # 指定容器启动时执行的命令(官方镜像已有,通常无需修改,除非有特殊启动脚本) # CMD ["catalina.sh", "run"]关键指令解析:
FROM:指定基础镜像,我们基于官方的Tomcat镜像构建。COPY:将宿主机构建上下文中的文件复制到镜像内。注意,第一个参数是相对路径,相对于Dockerfile所在的目录(构建上下文)。ENV:设置环境变量。JAVA_OPTS是Tomcat启动JVM时读取的参数,这里我们设置了堆内存初始值512M,最大值1024M,并使用G1垃圾收集器。EXPOSE:声明容器运行时监听的端口,这只是一个文档说明,实际映射需要在docker run时用-p指定。CMD:指定容器启动时的默认命令。官方Tomcat镜像的CMD已经是catalina.sh run,它会在前台启动Tomcat。如果我们不写,就会继承基础镜像的CMD。
5.2 构建镜像与运行:完成部署闭环
编写好Dockerfile后,在Dockerfile所在目录执行构建命令:
# -t 参数给镜像打标签,格式为 名称:版本。最后的 . 代表当前目录是构建上下文。 docker build -t mycompany/myapp:1.0 .构建过程会逐行执行Dockerfile中的指令。成功后,用docker images就能看到你刚构建的mycompany/myapp:1.0镜像。
现在,用这个自定义镜像运行容器:
docker run -d --name myapp-prod -p 80:8080 \ -e JAVA_OPTS="-Xms1g -Xmx2g -Dspring.profiles.active=prod" \ mycompany/myapp:1.0这里我们做了两件事:
- 将容器8080端口映射到宿主机的80端口,这样用户可以直接通过
http://宿主机IP访问。 - 通过
-e参数覆盖了镜像中设置的JAVA_OPTS环境变量,为生产环境分配了更大的内存,并设置了Spring Boot的活动配置文件为prod。这展示了镜像的灵活性:构建时设定默认值,运行时可根据环境动态覆盖。
这种将应用打包进镜像的方式,实现了真正的“一次构建,处处运行”。镜像就是你的交付物,在任何有Docker的环境下,运行命令即可启动完全一致的应用,彻底消除了环境差异。
6. 生产环境部署考量与多容器编排初探
单容器运行简单应用没问题,但对于稍微复杂点的生产环境,我们需要考虑更多:如何管理多个容器(比如Tomcat + MySQL + Redis)?如何保证容器挂掉后自动重启?如何集中查看日志?这就引出了容器编排的概念。虽然完整的编排(如Kubernetes)很复杂,但我们可以从Docker原生的docker-compose工具入手,它是定义和运行多容器应用的神器。
6.1 使用Docker Compose编排多服务
假设我们有一个经典的三件套应用:一个Spring Boot项目(打包成WAR,运行在Tomcat中),一个MySQL数据库,一个Redis缓存。用docker-compose.yml文件可以轻松定义它们。
创建一个docker-compose.yml文件:
version: '3.8' services: # MySQL数据库服务 mysql: image: mysql:8.0 container_name: app-mysql restart: always # 总是重启,确保服务高可用 environment: MYSQL_ROOT_PASSWORD: your_strong_root_password MYSQL_DATABASE: myappdb MYSQL_USER: myappuser MYSQL_PASSWORD: your_strong_user_password volumes: - mysql_data:/var/lib/mysql # 数据持久化到名为mysql_data的卷 ports: - "3306:3306" networks: - app-network # Redis缓存服务 redis: image: redis:7-alpine container_name: app-redis restart: always ports: - "6379:6379" networks: - app-network # 我们的Tomcat应用服务 webapp: build: . # 使用当前目录的Dockerfile构建镜像 container_name: app-tomcat restart: always depends_on: # 依赖关系,确保mysql和redis先启动 - mysql - redis environment: # 应用连接数据库和Redis的配置,通过环境变量传入 SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/myappdb?useSSL=false&serverTimezone=UTC SPRING_DATASOURCE_USERNAME: myappuser SPRING_DATASOURCE_PASSWORD: your_strong_user_password SPRING_REDIS_HOST: redis SPRING_REDIS_PORT: 6379 JAVA_OPTS: "-Xms1g -Xmx2g" ports: - "8080:8080" volumes: # 挂载日志目录,方便在宿主机查看 - ./logs:/usr/local/tomcat/logs networks: - app-network # 定义数据卷(用于持久化MySQL数据) volumes: mysql_data: # 定义自定义网络,让三个服务在同一个网络内,可以通过服务名互相访问 networks: app-network: driver: bridge在这个配置里,我们定义了三个服务(services),它们通过自定义的app-network网络互联,在容器内可以直接使用服务名(如mysql、redis)作为主机名进行访问,这是Docker Compose提供的服务发现机制。depends_on确保了启动顺序。volumes实现了MySQL数据的持久化,以及将Tomcat日志输出到宿主机目录。
运行这个应用栈只需要一条命令:
# 在当前包含docker-compose.yml的目录下执行 docker-compose up -d-d表示后台运行。Docker Compose会自动拉取镜像(或构建webapp服务)、创建网络、卷,并按依赖顺序启动所有容器。要停止并清理,执行docker-compose down。
6.2 生产环境最佳实践与安全提示
将Docker用于生产,除了编排,还有几个关键点必须注意:
镜像标签管理:永远不要使用
:latest标签部署生产环境。因为:latest是流动的,今天和明天拉取的可能是不同版本。必须使用明确的版本标签,如:1.0.2。最好结合CI/CD流水线,每次构建生成带版本号或Git Commit ID的镜像标签。日志管理:容器内的日志默认在
stdout和stderr输出。使用docker logs查看虽然方便,但在生产环境,日志需要集中收集和分析(如使用ELK栈:Elasticsearch, Logstash, Kibana,或Fluentd)。在Docker Compose或运行命令中,可以配置日志驱动,将日志直接发送到远程系统。数据持久化:牢记“容器是无状态的”。任何需要持久化的数据(数据库文件、上传的文件、应用日志)都必须通过
-v挂载宿主机目录或使用Docker Volume。切勿将重要数据只存放在容器内部。资源限制:默认情况下,容器可以使用宿主机的所有资源。这可能导致某个容器耗尽资源影响其他服务。使用
--memory、--cpus等参数为容器设置资源限制。docker run -d --name myapp --memory="1g" --cpus="1.5" myapp:1.0安全考虑:
- 非Root用户运行:默认容器内进程以root运行,存在风险。应在Dockerfile中使用
USER指令切换到非root用户。
FROM tomcat:9.0 # 创建非root用户并切换 RUN groupadd -r tomcat && useradd -r -g tomcat tomcat RUN chown -R tomcat:tomcat /usr/local/tomcat USER tomcat- 最小化镜像:使用
slim或alpine版本的基础镜像,减少攻击面。例如tomcat:9.0-jdk11-openjdk-slim。 - 定期更新:定期更新基础镜像和应用,修复安全漏洞。
- 非Root用户运行:默认容器内进程以root运行,存在风险。应在Dockerfile中使用
7. 疑难杂症排查与日常运维命令锦囊
即使准备得再充分,线上环境总会遇到各种问题。掌握一套排查问题的流程和命令,能让你快速定位和解决。
7.1 容器生命周期问题排查
问题1:容器启动后立即退出。这是最常见的问题。通常是因为容器内前台进程执行完毕退出了。
- 排查方法:查看容器日志。
docker logs [容器名]会打印出容器内进程的标准输出和错误。很可能你的应用启动失败,抛出了异常。 - 常见原因:应用配置文件错误、数据库连接失败、端口冲突、环境变量缺失等。
- 解决:根据日志错误信息修正。可以尝试以交互模式启动,方便调试:
docker run -it --rm [镜像名] /bin/bash,然后手动执行启动命令看看。
问题2:无法访问应用,但容器状态是Up。
- 排查步骤:
- 检查端口映射:
docker ps确认-p参数映射的端口是否正确。宿主机防火墙是否放行了该端口(如8080)?对于云服务器,还要检查安全组规则。 - 检查容器内应用状态:进入容器,
curl localhost:8080看看应用本身是否正常响应。 - 检查应用日志:
docker logs -f [容器名]查看应用是否有报错。 - 检查网络:如果涉及多容器通信,确保它们在同一个自定义网络中,并使用服务名访问。
- 检查端口映射:
问题3:容器占用了太多磁盘空间。Docker运行久了,会产生很多停止的容器、未使用的镜像、构建缓存和卷,占用磁盘。
- 清理命令:
# 删除所有已停止的容器 docker container prune # 删除所有未被使用的镜像(谨慎,会删除未被任何容器引用的镜像) docker image prune -a # 删除所有未被使用的卷(非常谨慎,确保卷内数据已备份) docker volume prune # 一键清理所有未使用的资源(容器、镜像、网络、卷,构建缓存) docker system prune -a
7.2 性能监控与资源查看
了解容器的资源使用情况,对于性能调优和故障预警至关重要。
docker stats [容器名]:实时显示容器的CPU、内存、网络IO、磁盘IO等使用情况。不加容器名则显示所有运行中容器的状态。docker top [容器名]:查看容器内运行的进程列表,类似于Linux的top命令。docker inspect [容器名]:获取容器(或镜像)的底层详细信息,以JSON格式输出。包括配置、网络设置、挂载卷、IP地址等。可以用--format参数过滤特定信息,例如docker inspect --format='{{.NetworkSettings.IPAddress}}' [容器名]获取IP。
7.3 镜像构建与推送的常见坑
构建上下文过大:Dockerfile中的COPY或ADD指令的文件来源是“构建上下文”(即docker build命令最后一个点.指定的目录)。如果这个目录很大(比如包含node_modules、.git),会导致构建过程非常慢,因为整个上下文会先打包发送给Docker守护进程。务必使用.dockerignore文件(类似.gitignore)来排除不需要的文件。
# .dockerignore 示例 .git node_modules *.log target/ *.md镜像层缓存:Dockerfile的每条指令都会生成一个镜像层,并且Docker会缓存这些层以加速后续构建。但这也可能导致问题,比如你COPY了一个配置文件,之后修改了文件内容,但Docker可能因为缓存而使用旧的层。在需要获取最新文件时(如COPY源代码),可以将容易变的指令放在Dockerfile后面,或者使用--no-cache选项强制重新构建:docker build --no-cache -t myapp:latest .。
推送镜像到私有仓库:首先给镜像打上符合仓库规范的标签:docker tag myapp:1.0 myregistry.com/myteam/myapp:1.0。然后登录仓库:docker login myregistry.com。最后推送:docker push myregistry.com/myteam/myapp:1.0。
从安装配置到生产部署,从单容器到多服务编排,Docker化Tomcat的旅程基本涵盖了中小型项目部署的核心场景。这套组合的优势在于极致的环境一致性和部署效率。一旦你熟悉了这套流程,就会发现回不去了——那种手动在服务器上配置环境、解决依赖冲突的日子,真的应该成为历史。剩下的,就是根据你的具体业务需求,去深入探索更高级的编排工具、监控体系和CI/CD流水线,让这套基础设施真正为你的业务敏捷性服务。