在拥有了一台属于自己的 VPS(如 1核 1G内存,配置了 2G Swap)后,很多新手在尝试部署 Java 项目时,往往会选择直接在服务器上安装 Maven 或运行 docker build。但现实很残酷:Java 编译极其消耗内存,1G 的内存在构建瞬间就会被挤爆,导致系统卡死或触发 OOM (Out Of Memory) 杀掉进程。
破局思路:本地构建,远程运行 利用性能强大的本地 Windows 电脑(作为宿主机)进行代码编译、打包和 Docker 镜像构建。然后将纯净的“镜像成品”传输到 VPS 上,VPS 只需要负责简单的“运行”即可。
以下是完整的实战记录,带你一步步避坑,完成低配服务器的完美部署。
阶段一:VPS 端数据库准备与数据导入#
由于资源有限,我们通过 Docker 启动一个轻量级、限制内存的 MySQL 容器。
1. 启动 MySQL 容器并限制内存#
在 VPS 上执行以下命令启动 MySQL 8.0。关键点在于 -m 400m,这能防止 MySQL 随着运行时间增长吞噬掉所有内存。
sudo docker run -d \
--name mysql-db \
--restart unless-stopped \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=你的数据库密码 \
-e MYSQL_DATABASE=你的数据库名 \
-m 400m \
mysql:8.0 \
--default-authentication-plugin=mysql_native_password2. 导入本地数据到 VPS 数据库#
不要尝试在服务器上安装笨重的可视化工具,直接通过命令行搞定:
- 第一步(Windows): 将本地导出的
xxx.sql文件传到 VPS。如果你的 VPS 修改过默认 SSH 端口,记得加上-P参数。
scp -P 你的SSH端口号 xxx.sql root@你的VPS_IP:/root/- 第二步(VPS): 将
sql文件从系统拷贝到 MySQL 容器内部。
sudo docker cp /root/xxx.sql mysql-db:/xxx.sql注意:这里的“mysql-db”是启动的MySQL容器的名字,上面的第一步的“–name”
- 第三步(VPS): 让 MySQL 容器执行该文件导入数据。
sudo docker exec -it mysql-db mysql -uroot -p你的数据库密码 你的数据库名 -e "source /xxx.sql"(验证:此时可通过本地电脑的 Navicat 或 IDEA 直连 VPS 的 3306 端口,确认数据导入成功。)
阶段二:本地 Java 项目调整与打包#
为了适应 1G 内存的限制,我们需要对 Java 环境做向下兼容的优化。
1. 修改代码中的数据库连接#
极易踩坑点: 之前代码里写的是 localhost:3306,现在必须修改为 你的VPS公网IP:3306,并且核对用户名、密码以及对应的数据库名称。
2. 将 Java 版本降级为 1.8 (Java 8)#
Java 8 内存占用更小,且与传统的 JSP 技术(依赖 javax.servlet)兼容性最好。
在 IDEA 的
Project Structure中,将 SDK 和语言级别修改为 1.8 和 8。打开 Maven 面板,依次双击
clean和package,在target目录下生成全新的.war包。
3. 编写 Dockerfile#
新建一个名为 vps-deploy 的文件夹,将 .war 文件拷贝进去,并在同级目录新建 Dockerfile(无后缀):
# 选用 Tomcat 9 搭配轻量级 Java 8 环境 (slim版本体积更小)
FROM tomcat:9.0-jre8-slim
# 清理 Tomcat 默认页面,保持环境纯净
RUN rm -rf /usr/local/tomcat/webapps/*
# 将项目 war 包复制并重命名为 ROOT.war,实现根目录直接访问(无需在 IP 后加项目名)
COPY 你的项目名.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080
CMD ["catalina.sh", "run"]阶段三:构建镜像与解决网络代理问题#
1. 本地构建 Docker 镜像#
在 vps-deploy 目录下打开终端,执行:
docker build -t my-jsp-app:v1 .避坑指南(网络拉取失败): 如果在构建时遇到 failed to fetch oauth token 报错,说明国内直连 Docker Hub 被墙。
- 解决方案: 启动你的代理客户端(如 v2rayN / Clash 等),开启 TUN 模式(虚拟网卡模式),让终端和 Docker Desktop 强制走代理网络,重新执行 build 即可顺利拉取基础镜像。
2. 导出镜像包#
网络畅通完成构建后,将镜像打包为一个离线的 .tar 文件:
docker save -o my-jsp-app.tar my-jsp-app:v1阶段四:VPS 最终部署与内存压榨#
1. 传输镜像到 VPS#
再次使用 scp 命令,把“集装箱”运上服务器:
scp -P 你的SSH端口号 my-jsp-app.tar root@你的VPS_IP:/root/2. 加载并运行容器(核心优化点)#
在 VPS 终端执行 sudo docker load -i my-jsp-app.tar 加载镜像。随后,使用以下命令运行你的 JSP 项目:
sudo docker run -d \
--name my-web-app \
--restart unless-stopped \
-p 80:8080 \
-e JAVA_OPTS="-Xms128m -Xmx256m" \
my-jsp-app:v1关键参数解析:
-p 80:8080:将服务器的80端口映射到容器的8080,实现在浏览器直接输入 IP 访问网站。-e JAVA_OPTS="-Xms128m -Xmx256m":绝对不能省的一句! 限制 Tomcat 的 JVM 初始内存为 128M,最大 256M。结合前面限制了 400M 的 MySQL,系统整体占用被严格控制在 700M 左右,完美适配 1G 内存机器!
3. 常见报错排查:端口冲突#
如果运行上述命令报错 Bind for 0.0.0.0:80 failed: port is already allocated,说明 80 端口被占用了(可能是之前测试用的 Nginx,或者自带的 Web 服务)。
- 排查命令:
sudo ss -tulnp | grep :80或sudo docker ps查找占用 80 端口的进程或容器。 - 解决: 使用
kill -9 PID杀掉进程,或docker rm -f 容器名删掉占位容器。然后重新运行启动命令即可。
部署总结: 通过“本地编译打包 -> 生成纯净镜像 -> 导出导入 -> 云端限制内存运行”这一套标准的工业级工作流,不仅保护了小内存 VPS 脆弱的性能,还极大提高了部署成功率。即使未来更换服务器,只需要把 tar 包拷走,你的项目也能在 1 分钟内在新服务器上满血复活!







