资讯详情

Spring Boot项目部署到阿里云CentOS 7服务器全流程指南

📅 2026/10/18 5:53:48 | 华诺云谱 👁 阅读
Spring Boot项目部署到阿里云CentOS 7服务器全流程指南
本地跑得好好的一部署到服务器就各种问题端口不通、进程没了、日志找不到、数据库连不上。这套“本地能跑”和“服务器能跑”之间的差距几乎每一个做过Java后端的人都在某个深夜体会过。今天这篇就用一台阿里云CentOS 7服务器把Spring Boot项目从零部署到能稳定运行覆盖环境安装、项目打包、进程守护、上线排查这几个环节全程记录下来适合第一次接触服务器部署的开发者也适合想把自己项目从IDE里挪到线上跑起来的同学。我不能保证看完这篇你的服务器就永远不会出问题但至少能让你少走我踩过的那些弯。整个过程我会尽量说清楚每个命令为什么这么写以及哪个环节最容易被忽略。1. 服务器选型与首次登录别在第一步就埋下隐患1.1 实例规格和系统版本的选择逻辑部署Spring Boot项目服务器配置不是越高越好也不是越低越省钱关键是匹配你的项目规模和预期流量。先说我自己的经验如果你只是个人项目、演示Demo、或者一个小型内部系统2核4G的实例足够用了。Spring Boot默认内嵌TomcatJVM堆内存给个512MB到1GB加上系统本身的开销4G内存能比较从容地跑起来。2核2G也能跑但碰到并发稍微上来一点GC频繁、CPU飙高是常态排查起来很费劲。如果是生产环境且有真实的业务流量建议至少4核8G起步。理由很简单JVM不是让你把内存全部塞满的留出给操作系统Page Cache、数据库连接、日志缓冲这些空间才能避免OOM时候的连锁反应。系统镜像选择CentOS 7.9注意几点一是选CentOS 7系的最新小版本因为旧版本可能存在已知的内核或安全补丁缺失二是不要选带“GUI”的版本纯命令行最小化安装就行图形界面在服务器上完全是浪费资源。云厂商一般会提供“系统镜像”和“自定义镜像”第一次部署选系统镜像里的CentOS 7.9即可。1.2 安全组规则到底该怎么配这一步很多人会忽略但90%的“连不上服务器”问题都出在安全组上。安全组是云厂商在虚拟机外层的防火墙和服务器内部的firewalld是两层概念两个地方都要放行只放行一个都没用。我建议的安全组配置如下端口协议授权对象用途22TCP你自己的IP别用0.0.0.0/0SSH登录80TCP0.0.0.0/0HTTP访问如果有Nginx或直接暴露443TCP0.0.0.0/0HTTPS访问8080TCP0.0.0.0/0Spring Boot默认端口看情况开3306TCP仅限自己的IP或干脆不开MySQL远程连接强烈建议不对外开放关于3306端口多说一句MySQL端口暴露到公网就是一场灾难。线上被勒索、被删库、被植入挖矿脚本的案例我见过不止一次。最稳妥的做法是永远不给3306开公网安全组规则需要管理数据库的时候就通过SSH隧道连或者直接用服务器命令行工具操作。1.3 SSH连接与密钥登录的细节服务器创建完成后第一件事就是登录上去。密码登录虽然简单但不建议长时间用一个是每次输入麻烦二是有被暴力破解的风险。我习惯的流程是先用密码登录然后立刻配置SSH密钥# 在本地机器上执行生成密钥对 ssh-keygen -t rsa -b 2048 -C your-emailexample.com生成后把公钥传到服务器上ssh-copy-id root你的服务器IP然后在服务器上修改SSH配置vim /etc/ssh/sshd_config找到这几项并修改PermitRootLogin prohibit-password PasswordAuthentication no PubkeyAuthentication yes修改完重启SSH服务systemctl restart sshd注意改配置之前先测试一下密钥登录是否已经生效。如果你把密码登录关了密钥又连不上只能通过云厂商的控制台VNC去救非常麻烦。改配置后不要立刻断开当前的SSH连接另开一个窗口测试确认能登录再断开。首次连接还有一个细节如果遇到连接很慢、输入密码后卡住的情况大概率是服务器侧的DNS反向解析超时。修改/etc/ssh/sshd_config里的UseDNS no可以解决。2. Java运行环境部署JDK安装不能只看“能跑”2.1 手动安装还是包管理器安装Spring Boot 2.x 需要JDK 8或更高版本Spring Boot 3.x 则要求JDK 17。CentOS 7自带的yum源里默认的Java版本是1.8足够覆盖大多数存量项目。安装方式有两种yum直接装或者手动下载JDK压缩包解压。我推荐使用yum安装openjdk-devel版本。原因有三点自动配置环境变量和系统路径省心安全补丁更新可以通过yum update统一管理不存在Oracle JDK的授权协议问题商业使用更省心对于绝大多数Spring Boot项目OpenJDK和Oracle JDK在运行性能上几乎没有区别不要被“一定要用Oracle JDK”的旧观念误导。2.2 JDK版本选择与配置环境变量直接安装JDK 8yum install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel-devel这个包非常关键它包含了javac编译器和完整的JRE运行环境。如果只装不带-devel的基础包很多工具链会发现找不到javac和JAVA_HOME。安装完成后验证java -version javac -version接下来手动配置JAVA_HOME环境变量。虽然yum安装已经让java命令可用但很多应用包括一些部署脚本、Maven、Jenkins需要读取JAVA_HOME这个变量才能正常工作。vim /etc/profile在文件末尾追加export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk export PATH$PATH:$JAVA_HOME/bin export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar这里要注意不同的yum安装版本路径可能略有不同建议先执行readlink -f $(which java)确认真实路径再写进JAVA_HOME。配置好后source /etc/profile echo $JAVA_HOME2.3 验证安装完成的标准一个常见的坑java -version能输出版本号不代表环境就完全OK了。我习惯用source /etc/profile之后在同一会话内执行以下验证which java which javac echo $JAVA_HOME三个命令都有输出且JAVA_HOME指向正确的路径才算真正装好。否则后面启动Spring Boot时用systemd写服务文件ExecStart里指定了/usr/bin/java这种绝对路径还好一旦用了$JAVA_HOME相关的变量或脚本就会因为环境变量没生效而找不到JVM。另外安装完系统后第一件事就该是yum update -y。把内核、glibc、openssl这些基础组件更新到最新版本既是安全需要也避免后面装MySQL、Redis时因为依赖库版本太低而报错。更新完重启一次服务器再继续下面的步骤。3. 数据库与缓存环境部署项目跑起来之前的“后勤保障”3.1 MySQL手动安装与初始化Spring Boot项目基本离不开数据库。CentOS 7默认源里不带MySQL需要手动配置仓库。先检查系统里是否有自带的MariaDB如果有则卸载避免端口冲突rpm -qa | grep mariadb yum remove -y mariadb*然后下载MySQL官方仓库包如果访问官方源慢可以用镜像源或云厂商的公共软件源替代wget https://repo.mysql.com/mysql57-community-release-el7-11.noarch.rpm rpm -ivh mysql57-community-release-el7-11.noarch.rpm yum install -y mysql-community-server安装完成后启动并设置为开机自启systemctl start mysqld systemctl enable mysqldMySQL 5.7及以上版本首次启动时会给root生成了一个临时密码记录在日志文件里grep temporary password /var/log/mysqld.log用这个临时密码登录mysql -u root -p然后执行安全初始化。这里一并说明密码策略的问题MySQL默认安装后validate_password插件启用要求密码至少8位且包含大小写字母、数字和特殊字符。如果你只是在测试环境且不想被这个规则折磨可以先设置一个符合要求的密码登录后用以下命令调整SET GLOBAL validate_password_policy LOW; SET GLOBAL validate_password_length 6;在初始化设置密码时我的建议是测试环境可以放宽生产环境密码一定要复杂并且定期更换。宁可多花5分钟设置一个强密码也别把数据库裸奔在公网上。3.2 数据库创建与授权的最佳实践应用需要自己的数据库和账号不建议直接用root连接业务。创建方式如下CREATE DATABASE yourdb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER youruserlocalhost IDENTIFIED BY YourPassword123!; GRANT ALL PRIVILEGES ON yourdb.* TO youruserlocalhost; FLUSH PRIVILEGES;这里关键点有两个第一字符集一定要指定utf8mb4。项目里如果要存表情符号或生僻字utf8字符集会报错或者乱码。这一点在创建库的时候就要固定下来后期再改字符集非常痛苦。第二授权范围默认只给localhost。Spring Boot应用和MySQL在同一台服务器上时连接串就写127.0.0.1不需要开远程。如果坚持要远程连接我不推荐再把localhost改成%并在安全组严格限制来源IP。3.3 Redis安装的同时把配置坑填了Redis在Spring Boot项目里通常承担缓存、Session共享、消息队列这几类角色。CentOS 7可以通过EPEL源直接安装yum install -y epel-release yum install -y redis安装后修改/etc/redis.confbind 127.0.0.1 protected-mode yes启动并验证systemctl start redis systemctl enable redis redis-cli pingRedis最大的安全风险就是暴露在公网且没有密码。如果应用和Redis在同一台机器上bind 127.0.0.1就足够了根本不需要设置密码。如果必须远程访问至少要做两件事改默认端口、设置强密码。另外一个容易被忽视的点Redis的maxmemory不配置的话默认64位系统不限制内存使用。一旦缓存数据量暴涨Redis会把服务器内存吃满触发OOM Killer把进程杀掉。在redis.conf里按服务器实际内存设置上限maxmemory 1gb maxmemory-policy allkeys-lru这个配置建议在一开始就设置好别等出问题了再补救。4. 项目打包上传把一个Spring Boot应用变成可运行文件4.1 Maven打包与跳过测试的时机本地项目打包用的是Maven服务器上不需要装Maven。本地在项目根目录执行mvn clean package -DskipTests这里-DskipTests的意思是跳过测试用例只编译。如果你没有写单元测试或者测试用例在打包环境中因为缺依赖而跑不起来用这个参数能节省好几轮构建时间。注意一个细节只跳过测试执行和完全跳过测试编译是两回事。-Dmaven.test.skiptrue才是连测试代码都不编译速度更快。但打包前建议至少在本地跑一遍完整测试确保代码没有明显问题再部署所以在服务器上追求速度用skipTests即可在本地CI里还是老老实实跑测试。打包完成后在target目录下可以看到两个文件your-project-0.0.1-SNAPSHOT.jar可执行jar包your-project-0.0.1-SNAPSHOT.jar.original原始jar不可直接执行Spring Boot的spring-boot-maven-plugin会生成一个包含内嵌Tomcat的可执行jar包。如果你看到.jar.original文件说明插件配置正常我们部署用的是不带original后缀的那个。4.2 上传工具选择与断点续传上传jar包到服务器有几种方式各有适用场景方式命令/工具适用场景scpscp xxx.jar rootIP:/opt/app/最简单Linux/Mac原生支持rsyncrsync -avP xxx.jar rootIP:/opt/app/支持断点续传大文件更稳rz/sz登录后执行rz选择本地文件Windows下比较方便但大文件容易中断宝塔面板文件管理器直接上传有图形界面时比较友好我个人的习惯是rsync特别是网络不稳定或者文件较大时rsync支持断点续传和增量传输失败重来也不会太心疼。小文件用scp就够了。上传目录建议统一放在/opt/app下。不要把jar包放在/root或者/home下这是很多人的习惯性操作但一旦目录权限或备份策略有变容易出意外。在服务器上创建目录mkdir -p /opt/app4.3 配置文件的环境差异化处理Spring Boot项目里application.yml放公共配置application-dev.yml放本地开发配置application-prod.yml放生产配置这是最常规的分环境管理方式。部署时启动命令里指定profilejava -jar /opt/app/your-project.jar --spring.profiles.activeprod关键点在于生产环境的数据库密码、Redis密码这些敏感信息不应该写在application-prod.yml里提交到代码仓库。我见过太多因为代码仓库泄露导致数据库被入侵的案例了。比较稳妥的做法是生产环境的敏感配置用环境变量覆盖或者在服务器上单独放一个配置文件用--spring.config.additional-location/opt/app/config/指定外部配置目录。这样代码仓库里的配置只有骨架真正的密码只存在于服务器上。数据库连接串的写法也要注意如果是同机部署jdbc:mysql://127.0.0.1:3306/yourdb比jdbc:mysql://localhost:3306/yourdb更快因为localhost在某些系统上会走socket而非TCP而JDBC驱动对socket的支持并不总是那么顺畅。5. 进程守护与开机自启让Java进程“死不了”5.1 nohup的局限与场景很多教程教的是一行命令启动nohup java -jar your-project.jar app.log 21 这行命令确实能启动项目而且关掉SSH窗口进程不会退出。但nohup有两个硬伤进程意外挂掉后不会自动重启。Java进程被OOM Killer干掉、代码里System.exit()被触发、服务器重启等等都需要你手动登录再启动一次。进程管理能力为零。没有start/stop/restart的概念想停止服务只能kill想重启只能先kill再nohup完全没有状态管理。对于临时调试或者一次性跑的demonohup可以接受。但作为一个长期运行的服务强烈建议一开始就使用systemd。5.2 systemd服务文件写法详解在/etc/systemd/system/下创建服务文件这是CentOS 7管理后台服务最标准的方式vim /etc/systemd/system/your-project.service内容如下[Unit] DescriptionSpring Boot Application Afternetwork.target [Service] Userroot WorkingDirectory/opt/app ExecStart/usr/bin/java -Xms256m -Xmx512m -jar /opt/app/your-project.jar --spring.profiles.activeprod Restartalways RestartSec5 SuccessExitStatus143 [Install] WantedBymulti-user.target逐个参数说明Afternetwork.target确保网络服务先就绪再启动应用否则启动时网络还没准备好应用里如果初始化了HTTP客户端或者注册到注册中心可能报错。Userroot指定运行用户。生产环境建议单独创建一个应用用户比如appuser只给应用目录的读写权限避免应用被攻破后直接拿到root权限。WorkingDirectory工作目录。Spring Boot生成日志、临时文件时的相对路径都以此为基准。如果不设置默认是/日志很可能写得到处都是排查时很难找。Restartalways进程退出后无论什么原因都自动重启。配合RestartSec5避免JVM刚启动就被反复拉起导致CPU飙升。SuccessExitStatus143这个很重要。systemd正常停止Java进程时发送的是SIGTERMJVM默认退出码是143。如果不在这个参数里标记143为正常退出码每次停止服务后systemd会认为进程是异常结束的从而触发Restartalways导致你明明执行了systemctl stop几秒后服务又自己起来了。这个坑特别隐蔽不写清楚很容易被整到怀疑人生。启用并启动服务systemctl daemon-reload systemctl enable your-project.service systemctl start your-project.serviceenable是把服务设置成开机自启start是立即启动。用systemctl status your-project.service查看运行状态用journalctl -u your-project.service -f实时查看日志。5.3 常用运维命令速查部署完成后下面这些命令会是你最常用的# 查看服务状态 systemctl status your-project.service # 查看日志实时跟踪 journalctl -u your-project.service -f # 查看日志最近100行 journalctl -u your-project.service -n 100 # 重启服务 systemctl restart your-project.service # 停止服务 systemctl stop your-project.service另外建议把服务配置文件备份一份。我的习惯是/opt/app/deploy/目录下留一份.service文件副本并写上简要说明这样即使系统重装了也能快速恢复部署。6. 上线后必须处理的四类问题端口、日志、内存、文件权限6.1 端口占用与防火墙的排查链路服务启动后访问不通这是一个非常常见的现象。排查链路应该是第一步确认进程是否真的在监听端口ss -lntp | grep 8080如果没有输出说明进程没有监听这个端口回到日志排查启动是否成功。第二步确认防火墙状态systemctl status firewalldCentOS 7的firewalld默认是开启的如果它拦截了8080端口即使云安全组放行了外面也访问不到。放行端口firewall-cmd --zonepublic --add-port8080/tcp --permanent firewall-cmd --reload第三步确认云安全组规则是否放行。安全组、服务器防火墙、进程监听三个环节任何一个断了都连不通。我遇到过一个很有意思的案例某开发者的服务启动成功、ss -lntp也能看到8080监听、firewalld也放行了但从公网就是访问不了。最后发现是服务器有多个网卡服务监听在了内网网卡的IP上而不是0.0.0.0。Spring Boot默认server.address是0.0.0.0理论上不会出这个问题但如果你在配置里显式指定了server.address就要注意是不是写错了IP。6.2 没有日志的排查就是盲人摸象日志是排查问题的第一依据但前提是日志有配置、有轮转、有保存策略。Spring Boot用logback记录日志默认情况下控制台输出。如果用systemd管理进程journalctl -u能直接看到标准输出这很方便但累积多了会占用/var/log/journal的磁盘空间。生产环境建议在application-prod.yml里配置日志文件logging: file: name: /opt/app/logs/app.log level: com.example: INFO同时配置logback的轮转策略避免单个日志文件无限增长。推荐使用logback-spring.xml覆盖默认配置设置MaxHistory、totalSizeCap这些参数按天滚动保留7天单文件大小限制在100MB。再看磁盘空间df -h日志写满磁盘导致应用崩溃这个问题太常见了。一定要做日志轮转或者至少定期清理。6.3 内存溢出与JVM参数调优Spring Boot应用的OOM表现通常是进程突然消失、dmesg里有Out of memory: Kill process或者日志里有java.lang.OutOfMemoryError。JVM参数里有两个关键配置-Xms256m -Xmx512m-Xms是初始堆大小-Xmx是最大堆大小。建议两个值相同避免运行时堆扩容带来的性能损耗。具体大小要根据服务器的总内存和业务量来定一般建议最多给服务器内存的50%-60%剩下给操作系统和外部程序用。排查OOM时给JVM加两个参数让它在OOM时自动导出堆转储文件-XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath/opt/app/logs/heapdump.hprof这样OOM发生时会有现场证据用jhat或者jvisualvm分析hprof文件就能看到是哪个对象占用最多内存。另外Java进程被系统杀掉不一定都是OOM也可能是系统内存整体不足触发了OOM Killer。排查时先看free -h再看dmesg两个方向一起确认。6.4 文件上传权限问题Spring Boot应用如果包含文件上传功能最常见的坑就是“上传成功但文件没有落盘”或者“前端访问不到上传的文件”。这类问题的排查核心是目录权限# 确认上传目录的属主和权限 ls -ld /opt/app/upload chown -R root:root /opt/app/upload chmod -R 755 /opt/app/upload如果你把应用运行用户改成了非root账号上传目录必须让该用户可写。这看起来很简单但在systemd服务里运行时进程的工作环境和手动SSH登录时完全不同环境变量、用户权限、工作目录都有差异。我建议在服务文件里显式指定User同时确保所有应用需要的目录权限都匹配这个用户。部署完服务后从页面上传一次文件测试确认无误再收工。千万别想当然觉得“我在服务器上手动执行时没问题服务跑起来也不会有问题”。7. 从“能跑”到“跑得稳”Nginx反向代理、HTTPS与备份7.1 Nginx反向代理的必要性Spring Boot默认监听8080端口用户直接访问http://IP:8080也可以但这样做有几点不便端口号暴露很丑、8080被大量扫描工具盯上、无法做多应用共存的80端口分流。用Nginx做反向代理对外统一暴露80端口内部根据路径或域名转发到不同端口是最常见的部署形态。安装Nginxyum install -y nginx新建站点配置vim /etc/nginx/conf.d/your-project.confserver { listen 80; server_name your-domain.com; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } client_max_body_size 50m; }client_max_body_size这行很重要。如果项目有文件上传功能默认Nginx只允许1MB大小的请求体不调大这个值大文件上传直接413。保存后校验配置并重启nginx -t systemctl restart nginx7.2 HTTPS配置的一次到位部署完HTTP能访问后强烈建议直接上HTTPS。现在浏览器对HTTP的标记越来越严格加上项目如果涉及登录、支付等敏感操作HTTPS是必须的。证书申请有两条路云厂商的免费证书通常是一年期或者手动签发Lets Encrypt证书。无论用哪种拿到证书文件后配置到Nginx里server { listen 443 ssl; server_name your-domain.com; ssl_certificate /etc/nginx/ssl/your-domain.pem; ssl_certificate_key /etc/nginx/ssl/your-domain.key; location / { proxy_pass http://127.0.0.1:8080; # 同上... } }配置完重启Nginx检查443端口是否监听systemctl restart nginx ss -lntp | grep 443HTTPS配置里最容易出的问题是证书路径错误或证书文件拼接错误多数浏览器会提示“连接不安全”。此时不要怀疑服务器配置先检查证书文件本身的完整性和匹配性。7.3 数据库定时备份的兜底方案无论你的项目多小数据库备份这件事不能省。血的教训是某开发者辛辛苦苦做了半年的项目一次误操作把表删了结果发现从没备份过只能对着屏幕发呆。一个最简单的定时备份方案用crontab实现。先写一个备份脚本vim /opt/app/backup.sh#!/bin/bash BACKUP_DIR/backup/mysql DATE$(date %F) mysqldump -u你的用户 -p你的密码 yourdb | gzip $BACKUP_DIR/yourdb_$DATE.sql.gz find $BACKUP_DIR -type f -mtime 7 -exec rm -f {} \;给脚本加执行权限加入定时任务chmod x /opt/app/backup.sh crontab -e加入一行0 2 * * * /opt/app/backup.sh每天凌晨2点备份一次保留7天的备份文件。这里有个比较重要的经验备份脚本执行前先用命令行手动跑一遍确认备份文件能正常生成且可解压恢复。定时任务里环境变量和手动执行不同如果脚本依赖某些环境变量比如PATHcrontab环境里可能找不到命令导致备份任务悄悄失败。脚本里用到mysqldump时建议用绝对路径或者脚本开头先source /etc/profile把环境导入。7.4 磁盘与内存监控的几个命令上线之后日常巡检必不可少我常用的命令就这几个# 磁盘空间重点看/根分区和/opt、/var分区是否快满 df -h # 内存使用重点关注available是否充足 free -h # 负载情况看CPU和内存占用最高的进程 top -c # IO情况如果磁盘响应很慢 iostat -x 2 3把这些命令记在笔记里每周跑一次或者用云厂商自带的监控报警功能设置阈值。日志膨胀、内存泄漏、磁盘耗尽这些问题越早发现处理成本越低。写在最后的个人经验整套流程走下来其实难度不在于某个步骤有多复杂而在于每个环节都可能埋着一个“看起来能用但其实不稳”的坑。我最想提醒你的一点是部署完能访问只是一个开始后面还要做进程守护、磁盘监控、备份策略把这些做完才叫“部署完成”。第一次部署的话我建议不要跳步把每一步的命令都理解后再执行。遇到报错就根据报错信息往上游查比如启动失败先看日志、日志没输出就看进程状态、进程没起来就看JVM参数和JAVA_HOME一层层查下去问题基本都能定位。慢慢地你就有自己的排查套路了那时候你会发现部署这件事其实比写代码简单多了。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑