Spring Boot应用从本地到公网部署全流程实战:Nginx、Docker与HTTPS配置
最近在技术社区里我注意到一个有趣的现象很多开发者尤其是刚接触后端或云原生技术的同学在搭建个人项目或学习环境时常常会陷入一个误区——认为所有开发工作都必须在“室内”即本地IDE或服务器完成。一旦遇到需要与外部服务、公网环境或真实物理设备交互的场景比如调用第三方API、部署到云服务器、连接物联网硬件就感到手足无措戏称这是要“到室外作业”。今天我们就来一期真正的“室外”实战。我们将不再局限于本地的localhost:8080而是把一个完整的Spring Boot应用从本地开发环境一路部署到公网可访问的云服务器上并配置好域名、HTTPS让它成为一个能被任何人访问的“室外”服务。这不仅仅是简单的部署更是一次对现代应用从开发到上线全链路的深度剖析。你会发现所谓的“室外”作业核心解决的其实是环境隔离、网络可达性、安全暴露与自动化运维这四个关键问题。如果你曾为“我的服务怎么让别人访问”而烦恼或者对Nginx、Docker、域名解析、SSL证书这些概念感到模糊那么这篇文章就是为你准备的。我们将从零开始用一个最经典的“用户管理”API作为示例完成从编码到上线的全过程并重点讲解每一步背后的“为什么”而不仅仅是“怎么做”。1. 这篇文章真正要解决的问题从“localhost”到“Anywhere”为什么我们需要把服务部署到“室外”这背后是几个非常实际的开发痛点演示与测试你写了一个很棒的功能想分享给同事、朋友或客户看。你不可能要求每个人都连到你的本地电脑或公司内网。移动端/多端联调开发手机App或小程序时后端API如果只在本地手机是无法直接访问你电脑IP的除非在同一个局域网且进行复杂配置。集成第三方服务许多第三方服务如微信支付、OAuth登录、短信发送的回调地址Callback URL要求必须是公网可访问的HTTPS域名。理解生产环境本地开发环境Windows/Mac与生产环境Linux服务器在文件路径、权限、依赖等方面存在差异提前在类生产环境中演练能避免“在我电脑上是好的”这类问题。本文将围绕一个具体目标展开将一个Spring Boot应用部署到云服务器并通过域名提供安全的HTTPS访问。在这个过程中你会清晰地看到开发室内与运维室外的边界并掌握打通这条通道的核心工具链和设计思想。2. 基础概念与核心原理在开始“室外”作业前我们先厘清几个关键角色和概念这能帮你理解整个部署地图。概念通俗解释在本次“室外”部署中的作用常见工具/服务云服务器 (ECS/VPS)一台24小时运行在数据中心的虚拟电脑。我们的应用最终运行的地方是“室外”的基地。阿里云ECS、腾讯云CVM、AWS EC2域名 (Domain)互联网上的门牌号如example.com。比IP地址好记。为用户提供访问我们服务的易记地址。任何域名注册商DNS 解析把域名翻译成服务器IP地址的电话簿系统。将我们购买的域名指向云服务器的公网IP。云服务商提供的DNS服务Nginx一个高性能的HTTP和反向代理服务器。1. 作为Web服务器处理静态请求。2. 作为反向代理将请求转发给后台的Spring Boot应用。3. 配置SSL实现HTTPS。开源软件需在服务器安装SSL/TLS 证书数字身份证用于加密浏览器和服务器之间的通信。让我们的服务从http://升级为https://保证传输安全也是很多第三方服务的强制要求。Let‘s Encrypt免费、云服务商购买Docker (可选但推荐)容器化技术将应用及其依赖打包成一个标准单元。解决“环境一致性问题”确保应用在本地和服务器上运行行为完全相同。开源容器引擎Git版本控制系统。将本地代码推送到远程仓库然后在服务器上拉取实现代码同步。GitHub, GitLab, Gitee核心流程原理图非Mermaid文字描述开发者在本地编写Spring Boot应用并测试。将代码推送至Git远程仓库如GitHub。在云服务器上通过Git拉取代码。在服务器上构建应用或用Docker构建镜像。使用Nginx接收来自公网用户浏览器的https://yourdomain.com请求。Nginx将请求反向代理到本地运行的Spring Boot应用例如http://127.0.0.1:8080。Spring Boot处理请求并返回结果经由Nginx返回给用户。接下来我们就按照这个原理一步步实现它。3. 环境准备与前置条件为了完成本次实战你需要准备好以下“装备”本地开发环境操作系统Windows 10/11, macOS 或 Linux。本文命令以Linux/macOS的bash为例Windows用户建议使用WSL2或Git Bash。Java开发套件JDK 8 或 11推荐11。确保java -version命令可用。构建工具Maven 3.6 或 Gradle。确保mvn -v或gradle -v命令可用。IDEIntelliJ IDEA, Eclipse 或 VS Code。Git用于版本控制。确保git --version命令可用。Docker (可选但强烈推荐)用于容器化部署。确保docker --version和docker-compose --version命令可用。“室外”服务器环境需提前购买和配置一台云服务器建议选择CentOS 7/8 或 Ubuntu 20.04/22.04 LTS系统的1核2G及以上配置。记下它的公网IP地址。一个域名在任何域名注册商购买一个域名例如your-awesome-app.com。如果仅用于测试可以使用云服务商提供的临时域名或直接使用IP访问但无法配置HTTPS。服务器基础配置能够通过SSH连接到服务器如使用ssh root你的公网IP。重要安全提醒云服务器请务必设置复杂的SSH密码或使用密钥对登录并禁用root的密码登录。本文为教程清晰起见部分操作使用root用户。在生产环境中建议创建具有sudo权限的专用用户来运行应用和服务。4. 第一步创建我们的“室内”应用 - Spring Boot API首先我们在本地室内创建一个简单的Spring Boot Web应用。这个应用将提供一个用户查询的RESTful API。使用 Spring Initializr 或IDE快速生成项目依赖选择Spring Web用于构建Web接口Lombok简化Java Bean代码可选但推荐Spring Boot Actuator用于健康检查可选对运维有帮助项目结构大致如下springboot-outdoor-demo ├── src/main/java/com/example/demo │ ├── DemoApplication.java // 主启动类 │ ├── controller/UserController.java // 控制器 │ ├── model/User.java // 数据模型 │ └── service/UserService.java // 业务服务 ├── src/main/resources/application.properties // 配置文件 └── pom.xml // Maven依赖管理核心代码实现1. 数据模型User.java// 文件路径src/main/java/com/example/demo/model/User.java package com.example.demo.model; import lombok.Data; Data // Lombok注解自动生成getter, setter, toString等方法 public class User { private Long id; private String username; private String email; }2. 服务层UserService.java// 文件路径src/main/java/com/example/demo/service/UserService.java package com.example.demo.service; import com.example.demo.model.User; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; Service public class UserService { // 模拟一个内存中的用户列表 private ListUser userList new ArrayList(); public UserService() { // 初始化一些测试数据 userList.add(new User(1L, alice, aliceexample.com)); userList.add(new User(2L, bob, bobexample.com)); userList.add(new User(3L, charlie, charlieexample.com)); } public ListUser getAllUsers() { return userList; } public User getUserById(Long id) { return userList.stream() .filter(user - user.getId().equals(id)) .findFirst() .orElse(null); } }3. 控制器UserController.java// 文件路径src/main/java/com/example/demo/controller/UserController.java package com.example.demo.controller; import com.example.demo.model.User; import com.example.demo.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; RestController RequestMapping(/api/users) public class UserController { Autowired private UserService userService; GetMapping public ListUser getAllUsers() { return userService.getAllUsers(); } GetMapping(/{id}) public User getUserById(PathVariable Long id) { return userService.getUserById(id); } }4. 主应用类DemoApplication.java// 文件路径src/main/java/com/example/demo/DemoApplication.java package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }5. 配置文件application.properties# 文件路径src/main/resources/application.properties # 应用服务端口默认为8080这里显式指定 server.port8080 # 应用名称 spring.application.nameoutdoor-demo # 可选关闭Spring Boot默认的Whitelabel错误页面让错误信息更清晰 server.error.whitelabel.enabledfalse本地运行与测试在项目根目录下执行mvn spring-boot:run # 或使用 gradle: ./gradlew bootRun看到Started DemoApplication in X.XXX seconds的日志后打开浏览器或使用curl测试curl http://localhost:8080/api/users预期返回JSON格式的用户列表。至此“室内”应用开发完成运行正常。5. 第二步为“室外”部署做准备 - 代码托管与Docker化为了让服务器能获取我们的代码并解决环境一致性问题我们需要做两件事推送代码到Git仓库以及将应用Docker化。5.1 推送代码到Git远程仓库在项目根目录初始化Git并推送到GitHub、Gitee或GitLab。# 初始化本地仓库 git init # 添加所有文件 git add . # 提交 git commit -m Initial commit: spring boot outdoor demo # 添加远程仓库地址 (请替换为你的仓库URL) git remote add origin https://github.com/your-username/springboot-outdoor-demo.git # 推送代码 git push -u origin main5.2 创建Dockerfile容器化部署的关键在项目根目录创建Dockerfile文件。它的作用是定义如何构建一个包含我们应用及其运行环境的镜像。# 文件路径Dockerfile # 第一阶段构建 # 使用Maven官方镜像包含JDK和Maven环境 FROM maven:3.8.4-openjdk-11-slim AS builder # 设置工作目录 WORKDIR /app # 将本地的pom.xml和源代码拷贝到镜像中 COPY pom.xml . COPY src ./src # 构建应用跳过测试并生成可执行的jar包 RUN mvn clean package -DskipTests # 第二阶段运行 # 使用更小的JRE运行镜像减小最终镜像体积 FROM openjdk:11-jre-slim # 设置工作目录 WORKDIR /app # 从构建阶段拷贝生成的jar包 COPY --frombuilder /app/target/*.jar app.jar # 暴露应用端口与application.properties中一致 EXPOSE 8080 # 设置容器启动时执行的命令 ENTRYPOINT [java, -jar, app.jar]关键解释多阶段构建第一阶段用完整的JDKMaven环境来编译打包第二阶段只包含运行所需的JRE使得最终镜像体积更小更安全。COPY --frombuilder这是多阶段构建的核心语法从上一个构建阶段复制文件。ENTRYPOINT定义容器启动时运行的命令。5.3 可选创建docker-compose.yml为了更方便地管理服务比如未来加入数据库可以在项目根目录创建docker-compose.yml。# 文件路径docker-compose.yml version: 3.8 services: outdoor-app: build: . # 使用当前目录的Dockerfile构建镜像 container_name: springboot-outdoor-demo ports: - 8080:8080 # 将宿主机的8080端口映射到容器的8080端口 restart: unless-stopped # 设置容器自动重启策略 # 可以在这里添加环境变量、卷挂载等配置 # environment: # - SPRING_PROFILES_ACTIVEprod现在我们的代码和容器化配置都已就绪。接下来我们就要登上“室外”的服务器开始部署。6. 第三步登陆“室外”服务器 - 基础环境搭建通过SSH连接到你的云服务器。ssh root你的服务器公网IP # 或使用密钥ssh -i /path/to/your-key.pem root你的服务器公网IP连接成功后我们首先搭建服务器所需的基础环境。6.1 更新系统并安装必要工具# 对于Ubuntu/Debian系统 apt update apt upgrade -y apt install -y curl wget git vim net-tools # 对于CentOS/RHEL系统 yum update -y yum install -y curl wget git vim net-tools6.2 安装Java运行环境如果使用Docker部署可跳过此步如果选择直接在服务器上运行Jar包需要安装JDK。# Ubuntu/Debian 安装 OpenJDK 11 apt install -y openjdk-11-jdk java -version # 验证安装 # CentOS/RHEL 安装 OpenJDK 11 yum install -y java-11-openjdk-devel java -version # 验证安装6.3 安装Docker和Docker Compose推荐方式Docker能极大简化环境配置是现代化部署的标准姿势。安装Docker Engine# 使用官方脚本安装Docker适用于大多数Linux发行版 curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh # 启动Docker服务并设置开机自启 systemctl start docker systemctl enable docker # 将当前用户加入docker组避免每次使用sudo操作后需退出SSH重新登录生效 usermod -aG docker $USER # 验证安装 docker --version安装Docker Compose# 下载Docker Compose的稳定版本请检查官网获取最新版本号 DOCKER_COMPOSE_VERSION$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep -oP tag_name: \K(.*)(?)) curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose # 赋予执行权限 chmod x /usr/local/bin/docker-compose # 验证安装 docker-compose --version6.4 安装并配置NginxNginx将作为我们服务的门户和反向代理。# Ubuntu/Debian apt install -y nginx # CentOS/RHEL yum install -y nginx # 启动Nginx并设置开机自启 systemctl start nginx systemctl enable nginx现在在浏览器中访问你的服务器公网IP如http://你的公网IP你应该能看到Nginx的默认欢迎页面。这说明Web服务器已经正常运行。7. 第四步在服务器上部署Spring Boot应用我们有多种方式在服务器上运行应用这里介绍最推荐的两种Docker Compose部署和传统Jar包部署。7.1 方式一使用Docker Compose部署推荐这种方式利用我们之前写好的docker-compose.yml是最简洁一致的方法。从Git仓库拉取代码# 切换到合适的目录例如 /opt cd /opt # 克隆你的项目仓库替换为你的仓库URL git clone https://github.com/your-username/springboot-outdoor-demo.git cd springboot-outdoor-demo使用Docker Compose构建并启动应用# 这行命令会执行根据Dockerfile构建镜像 - 创建并启动容器 docker-compose up -d-d参数表示在后台运行。验证应用是否运行# 查看容器状态 docker-compose ps # 应该看到状态为 Up # 查看应用日志 docker-compose logs -f outdoor-app # 使用curl在服务器内部测试API curl http://localhost:8080/api/users如果看到返回JSON数据说明Spring Boot应用在容器内已成功启动并监听8080端口。7.2 方式二传统Jar包部署如果你不想使用Docker也可以直接在服务器上运行Jar包。拉取代码并构建cd /opt git clone https://github.com/your-username/springboot-outdoor-demo.git cd springboot-outdoor-demo # 使用Maven打包确保已安装Maven mvn clean package -DskipTests运行Jar包# 后台运行并将日志输出到文件 nohup java -jar target/*.jar app.log 21 # 查看进程 ps aux | grep java # 测试API curl http://localhost:8080/api/users两种方式对比与选择建议Docker方式隔离性好环境一致依赖管理简单是云原生时代的主流。特别适合需要复杂依赖或多服务编排的场景。Jar包方式更轻量无需容器运行时适合对容器技术不熟悉或资源极其受限的环境。无论选择哪种方式我们的目标都是让Spring Boot应用在服务器的8080端口上运行起来。现在应用已经在“室外”服务器上跑起来了但还只能通过服务器的localhost:8080访问。下一步我们需要配置Nginx让公网用户能通过80/443端口访问它。8. 第五步配置Nginx反向代理 - 打通公网访问目前的情况是Nginx运行在服务器上监听80端口HTTP和443端口HTTPS。Spring Boot应用运行在服务器的8080端口或Docker容器的8080端口映射到宿主机的8080端口。我们需要让Nginx将收到的外部请求转发给内部的Spring Boot应用处理。8.1 配置Nginx反向代理编辑Nginx的站点配置文件。通常位于/etc/nginx/sites-available/Ubuntu或/etc/nginx/conf.d/CentOS。我们创建一个新的配置文件。# 创建一个新的配置文件例如叫 outdoor-demo vim /etc/nginx/conf.d/outdoor-demo.conf将以下配置内容粘贴进去请将your_domain_or_ip替换为你的域名或服务器IPserver { listen 80; # 监听HTTP的80端口 server_name your_domain_or_ip; # 你的域名或IP地址 # 访问日志和错误日志路径 access_log /var/log/nginx/outdoor-demo-access.log; error_log /var/log/nginx/outdoor-demo-error.log; # 反向代理配置将所有请求转发给本地的Spring Boot应用 location / { # proxy_pass 指令是反向代理的核心 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; # 超时设置 proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # 可选静态文件由Nginx直接处理效率更高 # location /static/ { # alias /path/to/your/static/files/; # expires 30d; # } }关键配置解释server_name指定这个配置块对哪个域名或IP生效。可以用_代表所有。location /匹配所有请求路径。proxy_pass http://127.0.0.1:8080;这是核心告诉Nginx将匹配到的请求转发到服务器本地的8080端口。proxy_set_header转发原始请求的头信息对于Spring Boot应用获取客户端真实IP、判断请求协议HTTP/HTTPS至关重要。8.2 测试配置并重载Nginx# 测试Nginx配置文件语法是否正确 nginx -t # 如果显示 syntax is ok 和 test is successful则重载Nginx使配置生效 systemctl reload nginx8.3 验证反向代理是否生效现在你不再需要直接访问http://服务器IP:8080。你应该直接访问http://你的服务器IP80端口。Nginx会自动将请求代理到8080端口的Spring Boot应用。在浏览器中访问http://你的服务器IP/api/users你应该能看到和之前本地测试一样的JSON数据。恭喜至此你的Spring Boot应用已经成功从“室内”走到了“室外”可以通过公网IP访问了。但这还不够专业和安全我们还需要给它一个“门牌号”域名和一把“安全锁”HTTPS。9. 第六步配置域名与HTTPS - 打造专业安全的服务使用IP访问既不友好也不安全。我们需要绑定域名并配置SSL证书。9.1 域名解析前往你购买域名的服务商控制台找到DNS解析管理页面添加一条A记录。记录类型A主机记录通常填表示主域名如yourdomain.com或www表示www.yourdomain.com记录值填写你的云服务器的公网IP地址TTL默认即可如10分钟DNS解析全球生效需要时间通常几分钟到几小时不等。你可以使用ping yourdomain.com或nslookup yourdomain.com命令来检查解析是否生效IP是否指向你的服务器。9.2 使用Certbot自动获取并配置Let‘s Encrypt免费SSL证书Let‘s Encrypt提供了免费的、自动化的SSL证书是个人项目和小型网站的绝佳选择。我们使用Certbot工具来自动化整个过程。安装Certbot和Nginx插件# Ubuntu/Debian apt install -y certbot python3-certbot-nginx # CentOS/RHEL 7 yum install -y epel-release yum install -y certbot python2-certbot-nginx # CentOS/RHEL 8 dnf install -y epel-release dnf install -y certbot python3-certbot-nginx运行Certbot获取并自动配置证书certbot --nginx -d yourdomain.com -d www.yourdomain.com将yourdomain.com替换为你的实际域名。按照提示操作输入你的邮箱用于接收证书过期提醒。阅读并同意服务条款。选择是否接收EFF的邮件可选否。Certbot会自动检测Nginx配置并询问是否将HTTP流量重定向到HTTPS。强烈建议选择“2: Redirect”这样所有HTTP请求都会自动跳转到安全的HTTPS。验证证书是否生效Certbot会自动修改你的Nginx配置文件/etc/nginx/conf.d/outdoor-demo.conf添加SSL相关配置并重载Nginx。 现在访问https://yourdomain.com/api/users浏览器地址栏应该显示安全的锁标志。同时访问http://yourdomain.com也会自动跳转到https://yourdomain.com。设置证书自动续期Let‘s Encrypt证书有效期为90天Certbot可以自动续期。通常它会自动创建一个定时任务cron job。你可以手动测试续期certbot renew --dry-run如果测试成功说明自动续期配置正常。查看最终的Nginx配置Certbot修改后你的配置文件会包含类似以下的关键部分server { listen 80; server_name yourdomain.com www.yourdomain.com; # 强制HTTP跳转到HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; # 监听HTTPS端口启用HTTP/2 server_name yourdomain.com www.yourdomain.com; # SSL证书路径由Certbot自动管理 ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; # 包含推荐的SSL安全配置 include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # ... 原有的反向代理location配置 ... location / { proxy_pass http://127.0.0.1:8080; # ... 其他proxy_set_header配置 ... } }现在你的服务已经是一个拥有专属域名和HTTPS加密的、完全“室外化”的专业服务了10. 运行结果与效果验证让我们系统地验证一下部署成果服务健康检查# 在服务器上检查Spring Boot应用进程 docker-compose ps # 或 ps aux | grep java # 检查应用自身的健康端点如果引入了Actuator curl http://localhost:8080/actuator/health # 检查Nginx状态 systemctl status nginx公网HTTP/HTTPS访问测试打开浏览器访问https://你的域名/api/users。应返回JSON格式的用户列表。访问http://你的域名/api/users。应自动301重定向到HTTPS版本。使用命令行工具测试curl -k https://你的域名/api/users # -k 参数暂时忽略证书验证用于测试 # 或者使用更规范的测试关注HTTP状态码和重定向 curl -I http://你的域名/api/users # 应返回 301 Moved Permanently curl -I https://你的域名/api/users # 应返回 200 OK关键组件连通性验证用户 - Nginx通过域名访问看到正确页面。Nginx - Spring Boot AppNginx日志/var/log/nginx/outdoor-demo-access.log应记录访问Spring Boot应用的控制台日志也应收到请求记录。SSL证书浏览器锁标志正常证书签发者为 “Let’s Encrypt”。11. 常见问题与排查思路在“室外”部署过程中你可能会遇到以下问题。这里提供快速排查思路。问题现象可能原因排查方式解决方案浏览器访问IP或域名显示 “无法连接” 或 “连接超时”1. 服务器防火墙未开放80/443端口。2. 云服务商安全组未放行端口。3. Nginx未启动或配置错误。1.systemctl status nginx检查Nginx状态。2. netstat -tlnpgrep :80 检查端口监听。3. 登录云控制台检查安全组/防火墙规则。访问域名显示 Nginx 默认页而非自己的应用1. Nginx配置文件中server_name未正确设置或未生效。2. 有默认配置如default优先级更高。1. 检查/etc/nginx/conf.d/outdoor-demo.conf中server_name是否正确。2. 检查/etc/nginx/sites-enabled/下是否有默认配置覆盖。1. 修正server_name。2. 禁用或删除默认站点rm /etc/nginx/sites-enabled/default(Ubuntu) 或 注释掉conf.d下的默认配置。3. 执行nginx -t systemctl reload nginx。访问应用返回 502 Bad Gateway1. Spring Boot应用未启动或崩溃。2. Nginx中proxy_pass的后端地址或端口错误。3. 应用启动过慢Nginx超时。1. 检查应用进程/容器状态docker-compose ps或 ps auxgrep java。br2. 检查应用日志docker-compose logs或查看应用日志文件。br3. 在服务器内部用curl http://127.0.0.1:8080/actuator/health 测试。HTTPS访问证书不安全警告1. 证书未正确配置或路径错误。2. 证书链不完整。3. 域名不匹配。1. 检查Nginx配置中ssl_certificate和ssl_certificate_key路径是否正确。2. 使用在线SSL检查工具如 SSL Labs诊断。3. 确认访问的域名与证书签发的域名完全一致。1. 使用certbot --nginx -d yourdomain.com重新运行Certbot修复。2. 确保证书文件存在且Nginx有读取权限。3. 如果是IP访问Let‘s Encrypt不支持IP证书需使用域名。应用更新后访问仍是旧版本1. Docker镜像未重建。2. Jar包未重新构建或进程未重启。3. 浏览器或CDN缓存。1. 检查服务器上代码是否为最新 (git pull)。2. 检查是否执行了重新构建和重启。1.Docker方式docker-compose down docker-compose up -d --build。2.Jar包方式杀死旧进程重新mvn package并启动。3. 清理浏览器缓存或为静态资源添加版本号。DNS解析不生效1. DNS记录设置错误。2. 本地DNS缓存。3. TTL未过期。1. 在域名控制台检查A记录设置。2. 使用nslookup yourdomain.com 8.8.8.8(Google DNS) 检查全球解析。3. 刷新本地DNS缓存 (ipconfig /flushdnson Windows,sudo dscacheutil -flushcacheon Mac)。1. 修正DNS记录。2. 等待DNS全球生效最长48小时。3. 降低TTL值以便更快生效。12. 最佳实践与工程建议将应用部署到“室外”只是第一步要让服务稳定、安全、可维护还需要遵循以下最佳实践使用非root用户运行应用在Dockerfile中创建专用用户或在服务器上使用www-data、app等用户运行Jar包遵循最小权限原则。# 在Dockerfile的RUN阶段添加 RUN addgroup -S spring adduser -S spring -G spring USER spring配置完善的日志确保应用日志、Nginx访问/错误日志都妥善配置和轮转。使用logrotate管理日志文件避免磁盘被撑满。# 查看Nginx日志 tail -f /var/log/nginx/outdoor-demo-error.log # 查看Docker容器日志 docker-compose logs -f --tail100设置监控与告警对于生产环境至少监控服务器的基础资源CPU、内存、磁盘和应用健康状态HTTP端点响应。可以使用云监控服务、Prometheus Grafana 或简单的定时脚本。实现CI/CD自动化将部署流程自动化。例如使用GitHub Actions、GitLab CI/CD或Jenkins在代码推送到特定分支时自动触发测试、构建镜像、推送到镜像仓库并在服务器上拉取新镜像重启服务。备份与回滚策略代码Git本身就是备份。数据库如果应用有数据库必须定期备份。服务器配置备份Nginx配置、SSL证书目录 (/etc/letsencrypt)、docker-compose.yml等关键文件。回滚在Docker中保留旧版本的镜像标签回滚时只需修改docker-compose.yml中的镜像版本并重启。安全加固服务器禁用SSH密码登录使用密钥对定期更新系统补丁配置防火墙如ufw或firewalld仅开放必要端口。应用Spring Boot应用应避免使用默认的/actuator端点暴露在公网或对其设置访问密码。依赖定期更新Maven/Gradle依赖修复已知安全漏洞。性能考虑Nginx缓存对于静态资源或变化不频繁的API响应可以配置Nginx缓存减轻后端压力。Docker资源限制在docker-compose.yml中为容器设置CPU和内存限制防止单个容器耗尽主机资源。JVM调优根据服务器内存大小调整Java应用的启动参数如-Xmx,-Xms。从“室内”的localhost:8080到“室外”的https://yourdomain.com这条路径涵盖了现代Web应用部署的核心环节。它不仅仅是步骤的堆砌更体现了开发与运维思维的融合环境标准化、配置代码化、流程自动化、安全前置化。掌握这套流程意味着你拥有了将任何本地原型快速转化为可公开访问、安全可靠服务的能力。无论是用于个人作品展示、小型创业项目启动还是作为理解复杂CI/CD和云原生部署的基石这都是一项极具价值的基础技能。建议你以此为起点继续探索容器编排Kubernetes、服务网格、基础设施即代码IaC等更高级的“室外”生存技巧。