Java Web部署
今天小编来分享下如何将本地写的Java Web程序部署到Linux上。
小编介绍两种方式:
部署基于Linux Systemd服务、基于Docker容器化部署
首先部署基于Linux Systemd服务
那么部署之前,要对下载所需的环境
软件下载
Linux(以ubuntu)
以下命令,为了方便,均以root用户操作
下载jdk
//查找下仓库中jdk
apt list | grep "jdk"
//下载openjdk17,这个版本根据你idea中选定的jdk即可
apt install -y openjdk-17-jdk
如何不小心下载错了,可以自行卸载
apt-get purge openjdk-17-jdk下载MySQL
//查看MySQL安装包
apt list | grep "mysql-server"
apt install -y mysql-server查看MySQL状态
systemctl status mysql执行MySQL安全脚本
执行此命令,会让MySQL运行安全性进一步提高
mysql_secure_installation后面的内容篇幅过长,就不截图了
内容大致如下:
设置密码验证插件:可以配置密码强度策略,确保用户设置强密码。
更改 root 用户密码:如果你没有在初始化时设置 root 密码,或者想要修改现有的 root 密码,可以通过此步骤完成。
移除匿名用户:默认情况下,MySQL 可能包含一个或多个匿名用户账户,这些账户允许任何人登录到 MySQL 服务器。移除这些账户可以增加安全性。
禁止 root 远程登录:确保 root 用户只能从本地机器登录 MySQL,减少被远程攻击的风险。
移除测试数据库:MySQL 默认提供了一个名为
test的数据库,任何人都可以访问。删除这个数据库可以避免潜在的安全风险。重新加载权限表:确保所有的更改都立即生效
卸载MySQL(出意外)
//停止服务
systemctl stop mysql
//卸载MySQL
apt-get remove --purge mysql-server mysql-client mysql-common
//删除MySQL配置文件及其数据
rm -rf /etc/mysql /var/lib/mysql
//清理残留文件和目录
apt-get autoremove
apt-get autoclean
//验证结果
MySQL -version登录数据库
//首次安装,默认是免密登录
mysql -u root
//如若不想对root用户不想进行免密登录、通过以下方式
//1.查看用户信息(在默认情况下,MySQL 8.0 使用 auth_socket 插件处理 root 用户的认证。)
SELECT User, Host, plugin FROM mysql.user WHERE User='root';
//2.更改roo用户的身份验证方法
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的新密码';
//刷新权限
FLUSH PRIVILEGES;
//退出
exit;
//重启MySQL服务(非root用户需+sudo)
systemctl restart mysql
//验证
mysql -u root -p导出sql文件
如若你的数据库创建在本地,比如windows,那么这里提供两种方式
命令行方式
//导出整个数据库
mysqldump -u 用户名 -p 数据库名 > 数据库名.sql
//导出某张表
mysqldump -u root -p blog_system comment > comment.sql
//只导结构,不包含数据
mysqldump -u root -p -d blog_system > blog_schema.sql
//导出多个数据库
mysqldump -u root -p --databases db1 db2 > backup.sql
//导出所有数据库
mysqldump -u root -p --all-databases > all.sql
//使用rz命令把本地的sql文件上传到Linux服务器(sz为下载文件到本地)
rz
//如若没有该命令,则通过以下命令进行安装
apt-get install -y lrzsz
//上传后的sql文件,执行以下命令即可恢复sql里面的数据,注意:得先创建对应的数据库
//示例
mysql -u root -p blog_system < blog_system.sql
图形化界面(navicat)
连接数据库

右键其中一个表

然后选择是否是仅结构或是结构和数据
点击后,会让你保存到自定义目录,然后等待导出即可
导出的sql文件,依旧通过rz命令上传或是拖拽上传,然后通过命令行方式恢复文件即可
//示例
mysql -u root -p blog_system < blog_system.sql
数据准备好后,接下来还有端口开放。
端口开放
如若在腾讯云、华为云、京东云等厂商购买服务器,还需官网上开启端口
进入官网页面:

进入控制台页面,点击轻量应用服务器
进入详情页面
点击防火墙

点击添加规则

配置参数

如若本地Java程序端口开放是9091,那么这里应用类型选自定义,来源选全部ipv4地址,端口填写9091,点击确定即可
查看防火墙
ufw status如若是inactive,则可以不用管,直接跳到后面即可
如若是active,那么可以通过以下命令进行关闭防火墙
ufw disable如若是想更加安全措施,参考以下命令
//windows win+R,cmd 查出本机ip
curl ifconfig.me
//添加防火墙规则
ufw allow from 本机IP 地址to any port 22
//如若想删除规则
ufw delete allow from 本机IP 地址to any port 22
本地文件编写
先介绍几个环境
• 开发环境: 开发⼈员写代码⽤的机器.
• 测试环境: 测试⼈员测试程序使⽤的机器.
• ⽣产环境(线上环境): 最终项⽬发布时所使⽤的机器. 对稳定性要求很⾼.
多环境配置
打开你的spring boot项目
打开application.yml文件
然后将此文件复制两份文件,命名如下
application-dev.yml(开发环境文件)、application-prod(生产环境文件).yml
为什么?
这是因为,复制两份文件,是为了不频繁改动applicaiton.yml文件内容,比如数据库密码
然后application.yml文件内容如下:
spring:
profiles:
active: @profile.name@pom.xml修改
与<dependencies>标签同级下,新建以下标签及其内容
<profiles>
<profile>
<id>dev</id>
<properties>
<profile.name>dev</profile.name>
<mysql.password>****</mysql.password>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prod</id>
<properties>
<profile.name>prod</profile.name>
<mysql.password>****</mysql.password>
</properties>
</profile>
</profiles>一个环境文件,就写一个<profile>标签,添加<activeByDefault>可以使得打包的时候,默认选中的是dev环境
重要一步!!!不要忘记刷新maven
刷新后,内容如下:

此时,你勾选prod,那就以生成环境配置为主,否则就是默认的dev。
点击Lifecycle下的package,打出jar包。
注意,如若想跳过测试,则点击图片中,长方形标出的按钮。
回到Linux服务器,使用rz命令把jar包上传到你选定的目录
动态获取不同环境的配置文件,这是Spring Boot 与 Maven 构建系统结合使用时的一种 “配置参数占位替换机制”
核心机制:Maven 构建时资源过滤 + profile 替换变量
选择prod时
Maven 会:
激活
<id>prod</id>的配置将
<properties>中的变量值(如profile.name=prod)注入然后自动替换
application.yml中的@profile.name@→prod
如若发现不生效,可以使用该设置,进行开启扫描过滤
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering> <!--开启过滤 -->
</resource>
</resources>
</build>
Linux文件配置
创建文件
vim /etc/systemd/system/xxxx.service添加文件内容
[Unit]
Description=Blog Manager Java Service
After=network.target
[Service]
# 运行用户,推荐非 root,开发测试可用 root
User=root
# 工作目录(jar 所在目录)
WorkingDirectory=/home/user/blog
# 启动命令(使用完整路径)
ExecStart=/usr/bin/java -jar /home/user/blog/blog_manager.jar
# 正常退出状态码
SuccessExitStatus=143
# 自动重启策略
Restart=on-failure
RestartSec=3
# 防止无限重启(60 秒最多重启 3 次)
StartLimitIntervalSec=60
StartLimitBurst=3
# 日志输出
StandardOutput=append:/var/log/blog_manager.log
StandardError=append:/var/log/blog_manager.err
# Kill 方式(强制终止)
KillMode=process
KillSignal=SIGTERM
[Install]
WantedBy=multi-user.target
重新加载配置
systemctl daemon-reload启动服务
systemctl start xxxx查看状态
systemctl status xxxx然后可以通过http://你的公网ip地址:配置的端口/首页html文件 进行网站访问
其工作原理大致如下:
systemctl daemon-reload让 systemd 重新加载配置systemctl start xxxx时,systemd 会:检查网络是否就绪(After=network.target)
切换到指定工作目录
以 root 用户执行 Java 命令
监控进程状态,按策略处理异常
记录标准输出和错误到日志文件
即.service文件中规定了如何做,那么systemd就执行什么。
快速测试jar包
nohup java -jar xxxxxx.jar >/logger/xxx.log &这个nohup指令,全称是no hang up 用于在系统后台不挂断的运行命令,退出终端不受影响
Docker部署
那么接着,接下来小编介绍,基于Docker容器化部署
进入Linux命令行、小编以root用户进行操作,非root用户,建议命令加上sudo
一:准备工作
1.更新软件包:
//检查更新软件包列表
apt-get update
//升级所有可升级的软件
apt-get upgrade
//清理无用的旧依赖(这一步可选可不选)
apt autoremove2.安装docker前置依赖:
apt-get -y install apt-transport-https ca-certificates curl software-properties-common安装组件说明:
3.添加docker官方的GPG密钥(信任源)
curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg注意:使用阿里云镜像站点的GPG密钥,速度快且稳定
命令意思是:
从阿里云镜像站点下载GPG公钥
用 GPG 工具把它处理成 apt 能识别的格式
保存在 /etc/apt/keyrings/docker.gpg 中
-fsSL参数解释:
-f:表示在服务器错误时阻止返回错误页面,直接返回错误码 22。-s:启用安静模式,不显示进度条或错误信息。 13-S:启用 SSL 加密协议,确保数据传输安全
4.添加docker软件源:
echo "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker-ce.list参数解释: deb:表示这是一个Ubuntu的二进制软件源(非源码包)
[arch=amd64]:指定该源适合于64位x86架构
$(lsb_release -cs):获取当前Ubuntu系统发行版代号
stable:使用docker的稳定版本,(非测试版edge或nightly)
tee:写入文件(tee 既能输出到屏幕又能写入文件)。
5.再次更新软件包列表
让系统再次添加刚刚的docker的源:
apt-get update如若发生NO_PUBKEY,返回第三步重新导入密钥
6.安装docker引擎
apt-get install -y docker-ce docker-ce-cli containerd.io软件包功能如下:
1. docker-ce(Docker Community Edition)
作用:Docker 的核心引擎(主程序),负责容器的创建、运行和管理。
包含的主要功能:
dockerd:Docker 守护进程(后台服务)。Docker 的 REST API(供客户端如
docker命令行工具调用)。容器生命周期管理(
create/start/stop/rm等)。
2. docker-ce-cli(Docker 命令行工具)
作用:Docker 的官方命令行客户端(
docker命令)。关键功能:
提供
docker命令(如docker run、docker ps等)。与
dockerd守护进程通信(通过/var/run/docker.sock)。
3. containerd.io(容器运行时)
作用:Docker 依赖的底层容器运行时(由 Docker 剥离出的核心组件)。
功能:
管理容器的底层操作(如镜像拉取、容器启动、存储管理)。
被
dockerd调用,负责与 Linux 内核交互(通过runc等工具)。
7.验证docker是否安装成功
docker --version类似信息如下:
Docker version 28.3.3, build 980b856
还可以查看docker详细信息
docker info8.配置镜像加速器
配置镜像加速器,后续进行docker pull操作的时候,可以解决拉取缓慢/失败问题
值得注意的是:2024年底起,阿里云已经停用公共镜像加速器
详情如下:配置镜像加速器_容器镜像服务(ACR)-阿里云帮助中心
1.创建docker配置文件:
小编使用的是腾讯云服务器,所以使用了腾讯云的镜像加速器
sudo mkdir -p /etc/docker
cat > /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
EOF值得注意的是,该网址,不可直接在浏览器访问,
原因:
该地址是一个 Docker Registry 镜像服务,遵循 Docker 的 API 协议(如
v2),仅响应 Docker 客户端的请求(如docker pull)。浏览器访问会返回
404或401 Unauthorized,因为它期望的是 Docker 客户端的特定 HTTP 请求。
你可以通过以下命令进行测试:
curl -I https://mirror.ccs.tencentyun.com
常见的镜像加速器:
2.重启docker使配置生效
systemctl restart docker3.验证加速器是否生效
docker info | grep -A 3 "Registry Mirrors"4.运行第一个容器,测试
docker run hello-world注意,首次运行,会没有该容器,然后会从hub中,拉取hello-world
二:构建容器,并运行
1.修改application-prod.yml文件
URL替换:
url: jdbc:mysql://172.17.0.1:3306/blog_manger?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
//值得注意的是,url还可以写成这样
url: jdbc:mysql://host.docker.internal:3306/blog_manager?useSSL=false&allowPublicKeyRetrieval=true
原因: docker容器的网络隔离性,每个容器有独立的网络命名空间,127.0.0.1仅指向容器内部,不是主机的数据库
为什么是 172.17.0.1?
Docker 默认创建网桥
docker0,子网通常是172.17.0.0/16。宿主机在该网络中的 IP 固定为
172.17.0.1(类似路由器角色)。容器内访问
172.17.0.1即访问宿主机。
前提是MySQL得监听:0.0.0.0.
那么小编使用的时MySQL监听:0.0.0.0,修改MySQL配置文件的操作,文章末尾会介绍另一种方案
2.修改MySQL配置文件以及权限
cd /etc/mysql/mysql.conf.d/mysqld.cnf
//修改配置文件,找到bind-address,改成以下内容
bind-address= 0.0.0.0重启防火墙:
systemctl restart mysql修改MySQL权限
//登录MySQL
mysql -u root -p
//查看当前的 root 用户及其允许连接的 host
SELECT user, host FROM mysql.user WHERE user = 'root';
// 修改现有 root@localhost 用户的 host,或创建新的 root@'172.17.0.%' 用户
// 如果您想让现有的 root 用户可以从任何地方连接 (不推荐生产环境):
ALTER USER 'root'@'localhost' IDENTIFIED BY '*****'; -- 确保密码正确
ALTER USER 'root'@'localhost' RENAME TO 'root'@'%';
// 或者,更推荐的是,创建一个新的 root 用户,允许从 Docker 网段连接
CREATE USER 'root'@'172.17.0.%' IDENTIFIED BY '***';
//允许该网段对其数据库有读写操作
GRANT ALL PRIVILEGES ON blog_manger.* TO 'root'@'172.17.0.%' WITH GRANT OPTION;
//刷新客户端
flush privileges;如若防火墙关闭了,那么可以到下一步了,没有,那么推荐使用以下操作
防火墙:
# 允许 SSH (22 端口)
sudo ufw allow ssh
# 允许您的博客应用外部访问端口 (9091)
# 假设您希望从外部访问您的博客系统前端,需要开放这个端口
sudo ufw allow 9091/tcp
# 允许 Docker 宿主机内部网络(172.17.0.0/16)访问 MySQL 端口 (3306)
# 这是让您的 Docker 容器能够连接 MySQL 的关键
sudo ufw allow from 172.17.0.0/16 to any port 3306 proto tcp
# 设置默认策略:拒绝所有传入连接,允许所有传出连接
# 这表示除了您明确允许的规则,其他所有外部尝试连接都会被拒绝
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 启用 UFW 防火墙
sudo ufw enable
# 检查 UFW 状态,确认规则已生效
sudo ufw status verbose3.首先创建一个目录,用来存放jar包和Dockerfile文件
mkdir blog_dokcer然后把jar包进行复制到该目录,或者直接传输到该目录
小编这里重命名为blog-docker.jar
4.编写Dockerfile文件
# 使用官方 Java 镜像作为基础镜像
FROM openjdk:17-jdk
# 设置工作目录
WORKDIR /blog_docker_work
# 拷贝 jar 包到容器中
COPY blog-docker.jar blog-docker.jar
# 暴露端口(假设 Spring Boot 配置了 9091)
EXPOSE 9091
# 启动命令
ENTRYPOINT ["java", "-jar", "blog-docker.jar"]5.构建镜像
docker build blog-docker:latest .注意 .表示,你需要在当前创建的Dockerfile目录进行该操作
查看该镜像是否存在
docker images6.运行容器
docker run -d --name blog-docker-container -p 9091:9091 blog-docker:latest
//如若yml文件中写了host.docker.internal:3306,那么运行容器就是这个命令:
docker run -d \
--name blog-docker-container \
-p 9091:9091 \
--add-host host.docker.internal:host-gateway \ # 关键:映射宿主机 IP
blog-docker:latest接下来通过http://你的公网ip地址:配置的端口/首页html文件 进行网站访问
删除容器和镜像
//找到容器ID,或者容器名
docker ps
//删除容器ID,或者容器名
docker rm 容器名/容器ID
//找到镜像ID
//方式一
docker inspect --format='{{.Image}}' 容器ID
//方式二
docker images
//删除镜像
docker rmi 镜像ID
7.查看日志
如若发现网站有访问接口报错,或者,想查看后端日志
可通过以下命令:
docker logs -ft blog-docker-container | grep -i "error\|exception"那么刚刚一种部署方式是docker连接宿主机的数据库的,那么接下来分享另一种方法
独立使用MySQL容器
1.创建docker网络
docker network create blog-network2.拉取MySQL镜像
docker pull mysql:8.0 # 可显式拉取,或让 run 自动拉取3.启动Mysql容器并导入数据
如需本地Windows电脑数据库中的数据,可参考导出本文sql文件导出方式Java Web部署
导出的文件,要上传到Linux指定的目录下
运行MySQL容器:
docker run -d \
--name mysql-container \
--network blog-network \ # 加入网络
-e MYSQL_ROOT_PASSWORD=123456 \ # 设置 root 密码
-e MYSQL_DATABASE=blog_manger \ # 创建默认数据库
-v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql \ # 导入 SQL
-v mysql_data:/var/lib/mysql \ # 持久化数据(自动创建卷)
-p 3306:3306 \ # 可选:暴露端口给宿主机
mysql:8.0 # 使用 MySQL 8.0
注意,如若之前没有拉取镜像,这一步,docker也会拉取MySQL镜像
参数说明:
3.验证数据是否导入
docker exec -it mysql-container mysql -uroot -p123456通过此命令,可进入MySQL命令行交互
docker exec 是 Docker 命令行工具中用于在运行中的容器内执行命令的一个非常有用的命令。
常用选项
-d或--detach:在后台运行指定的命令。-i或--interactive:即使没有附加也保持 STDIN 开放。通常与-t一起使用。-t或--tty:分配一个伪终端。这对于交互式命令(如 bash shell)非常有用。--privileged:给予执行命令的容器额外的权限。-u或--user:以指定的用户身份(格式为 UID:GID)运行命令。
4.修改yml文件
spring:
datasource:
url: jdbc:mysql://mysql-container:3306/blog_db?useSSL=false
username: root
password: 1234565.构建镜像
docker build -t blog-docker:latest .6.运行容器
docker run -d --name blog-docker-container --network blog-network -p 9091:9091 \
blog-docker最后,访问url,进行验证即可
最后小编分享下,对于docker中的build 、run命令常见选项
构建
命令格式:
docker build [OPTIONS] PATH | URL | -常用示例:
docker build -f Dockerfile -t blog-manager:latest .
docker build -t nginx-custom:dev --no-cache .
docker build -t myapp --build-arg VERSION=1.0 .
运行
命令格式:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]常用示例:
docker run -d --name blog -p 8080:8080 blog-manager:latest
docker run -e SPRING_PROFILES_ACTIVE=prod blog-manager:latest
docker run --restart=always -d --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:8.0