前端打包

碎念念

Java项目是真的栈内存,JVM参数调几下还是难受

前提先包装nodejs,建议使用 nvm 进行安装方便版本管理(前端各种版本兼容问题很多)

总体逻辑:先install,再service、build(必须先安装前端项目需要的依赖才能正常启动服务和打包)

具体install、service、build的命令不用去管,根据使用的框架不同有不同的打包方式和命令,它们都定义在package.json文件中,我们只需直接使用npm、yarn、npmn之类的包管理工具简化命令(具体选哪个看你的喜好吧,nodejs安装后默认有npm,其他的yarn、npmn也好都可以使用npm先安装后使用),所以你需要做的就是形如:yarn install、yarn service、yarn build

打包成功后,会在根目录下生成dist目录,上传到服务器的静态资源路径中即可

环境搭建

#todo/note 可以先参考之前的文章:打造舒适开发环境

根据具体情况,选择安装方式,centos为例(使用包管理器:yum)

本机

直接在服务器物理主机上安装

Nginx

更新系统软件包列表。

sudo yum update

安装 Nginx 命令。

sudo yum install nginx

安装完成后,可以使用以下命令启动 Nginx。

sudo systemctl start nginx

同时还需要设置 Nginx 开机自启。

sudo systemctl enable nginx

docker

通过Docker安装

项目部署

说白了,两种方法:物理机部署或者容器部署

物理机部署

以Java程序为例,前面步骤一致

  1. 安装JDK,配置Java环境
  2. 后端项目、前端项目打包
  3. 上传打包文件
  4. 若使用Nginx反代,事先安装并配置反代路由(建议物理机安装)
    最后,我们要启动Jar包,有两种方式:直接启动或者服务单元
Abstract
  1. 使用 nohup 启动命令:

    • nohup:nohup 是一个 Unix/Linux 命令,用于在后台运行命令,同时将命令的输出重定向到一个指定的文件中,即使当前终端关闭,命令也会继续运行。
    • /usr/local/java/zulu17.44.53-ca-jdk17.0.8.1-linux_x64/bin/java:Java 可执行文件的路径。
    • -Xms2048m -Xmx2048m:指定 Java 虚拟机的初始堆大小和最大堆大小。
    • -D 参数:通过 -D 参数设置 Java 系统属性。
    • -jar /home/12306/index12306-gateway-service.jar:指定要执行的 Java 可执行 JAR 文件。
    • > logs/index12306-gateway-service.file 2>&1:将标准输出和标准错误重定向到日志文件中。
    • &:在命令末尾加上 & 符号表示以后台方式运行命令。
  2. 服务单元:详情参考文章:Linux常用命令 > 启动系统服务

    • 服务单元是一种管理和控制系统服务的机制,通常用于 Linux 系统上。你可以创建一个服务单元来定义服务的启动、停止、重启等操作,以及服务的各种配置参数。
    • 使用服务单元可以方便地管理和控制系统服务,并且可以在系统启动时自动启动服务。

总的来说,使用 nohup 命令启动 Java 程序是一种简单的方式,适用于一次性或者临时的任务。而使用服务单元则更适合长期运行的服务,并且提供了更多的管理和控制功能。

容器部署

Tip
  • 编写dockerfile,适合单体
  • 编写docker-compose,适合微服务,容器编排,网络配置等,适合个人使用,一键启动
  • 但事实上两者都可以容器编排,两者可以结合使用

教学示例

以下是一个简单的 Dockerfile 示例,用于构建一个基于 OpenJDK 的 Java 应用容器镜像:

# 使用 OpenJDK 镜像作为基础镜像
FROM adoptopenjdk/openjdk17:alpine-jre

# 设置容器中的工作目录
WORKDIR /app

# 复制 Jar 文件到容器中
COPY index12306-aggregation-service.jar /app/
COPY index12306-gateway-service.jar /app/

# 复制 Nginx 配置文件到容器中
COPY nginx.conf /etc/nginx/nginx.conf

# 复制静态前端页面到容器中
COPY dist /usr/share/nginx/html

# 安装 Nginx
RUN apk update && \
    apk add --no-cache nginx && \
    rm -rf /var/cache/apk/*

# 暴露 Nginx 端口
EXPOSE 80

# 定义容器启动时运行的命令
CMD ["sh", "-c", "java -Xms2048m -Xmx2048m \
-Dunique-name=-lzy12306 \
-Dframework.cache.redis.prefix=lzy12306: \
-Dspring.data.redis.password=<REDIS_PASSWORD> \
-Dspring.data.redis.port=<REDIS_PORT> \
-Dspring.data.redis.host=<REDIS_HOST> \
-Drocketmq.name-server=<ROCKETMQ_SERVER> \
-Dspring.cloud.nacos.discovery.server-addr=<NACOS_SERVER> \
-Dpay.alipay.notify-url=<ALIPAY_NOTIFY_URL> \
-jar /app/index12306-aggregation-service.jar > /app/logs/index12306-aggregation-service.file 2>&1 \
& java -Xms2048m -Xmx2048m \
-Dunique-name=-lzy12306 \
-Dframework.cache.redis.prefix=lzy12306: \
-Dspring.data.redis.password=<REDIS_PASSWORD> \
-Dspring.data.redis.port=<REDIS_PORT> \
-Dspring.data.redis.host=<REDIS_HOST> \
-Dspring.cloud.nacos.discovery.server-addr=<NACOS_SERVER> \
-jar /app/index12306-gateway-service.jar > /app/logs/index12306-gateway-service.file 2>&1 \
& nginx -g 'daemon off;'"]

这个 Dockerfile 的主要作用是:

  1. 基于 adoptopenjdk/openjdk17:alpine-jre 镜像构建一个容器镜像。
  2. 设置容器的工作目录为 /app。
  3. 将 index12306-aggregation-service.jar 和 index12306-gateway-service.jar 文件复制到容器的工作目录。
  4. 复制 Nginx 配置文件 nginx.conf 到容器中的 /etc/nginx/nginx.conf。
  5. 复制静态前端页面 dist 到容器的 /usr/share/nginx/html 目录。
  6. 使用 apk 包管理器安装 Nginx。
  7. 暴露 Nginx 的80端口。
  8. 定义容器启动时运行的命令,启动 Java 服务和 Nginx 服务。

关于 Docker Compose 文件的编写,你可以创建一个名为 docker-compose.yml 的文件,内容如下:

version: '3'
services:
  app:
    build: .
    ports:
      - "80:80"
    volumes:
      - ./logs:/app/logs

这个 docker-compose.yml 文件指定了一个名为 app 的服务,使用当前目录下的 Dockerfile 构建容器镜像,并将容器的 80 端口映射到主机的 80 端口。同时将容器内的日志目录 logs 映射到主机的 ./logs 目录。

完善实例

这是开源项目Halo提供的docker-compose,这是直接使用对方已经通过dockerfile构建好并发布到容器仓库的halo和mysql镜像来构建服务,只需配置好挂载卷、端口映射、启动命令、网络桥接即可,还可以设置服务的启动顺序和依赖顺序。最终只需要在自己服务器创建一个这样的docker-compose文件并一键启动即可。

version: "3"

services:
  halo:
    image: halohub/halo:2.9
    container_name: halo
    restart: on-failure:3
    depends_on:
      halodb:
        condition: service_healthy
    networks:
      halo_network:
    volumes:
      - ./:/root/.halo2
    ports:
      - "8090:8090"
    command:
      - --spring.r2dbc.url=r2dbc:pool:mysql://halodb:3306/halo
      - --spring.r2dbc.username=root
      # MySQL 的密码,请保证与下方 MYSQL_ROOT_PASSWORD 的变量值一致。
      - --spring.r2dbc.password=XXX
      - --spring.sql.init.platform=mysql
      # 外部访问地址,请根据实际需要修改
      - --halo.external-url=https://cytl.ink
      # 初始化的超级管理员用户名
      - --halo.security.initializer.superadminusername=admin
      # 初始化的超级管理员密码
      - --halo.security.initializer.superadminpassword=root

  halodb:
    image: mysql:8.0.31
    container_name: halodb
    restart: on-failure:3
    networks:
      halo_network:
    command: 
      - --default-authentication-plugin=mysql_native_password
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_general_ci
      - --explicit_defaults_for_timestamp=true
    volumes:
      - ./mysql:/var/lib/mysql
      - ./mysqlBackup:/data/mysqlBackup
    ports:
      - "3306:3306"
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"]
      interval: 3s
      retries: 5
      start_period: 30s
    environment:
      # 请修改此密码,并对应修改上方 Halo 服务的 SPRING_R2DBC_PASSWORD 变量值
      - MYSQL_ROOT_PASSWORD=XXX
      - MYSQL_DATABASE=halo

networks:
  halo_network:

备案

Tip
  • 备案主要是公信力,使用国内服务器空间必须备案。开启网站的域名访问,开启https,加密传输流量
  • 使用国外服务器空间,无上述限制

之前备案过一次,之后如果再次备案很多基本信息会默认填写

备案指的是域名备案,但域名备案必须依赖云空间

只要你使用的云空间(服务器)是国内的,那么你要想域名访问网站就必须完成备案

免备案方法

不用备案,域名访问国内空间

CloudFlare回源

利用cloudflare让未备案域名自动转发至自己服务器地址_cloudfare转发-CSDN博客
页面规则转发,免费用户可以设置三个,会暴露ip

Nginx反代

由于国内服务器允许未备案域名使用除80、443端口访问,所以我们可以直接将域名解析到国外服务器IP上,然后在国外服务器上设置反向代理,这种方法本质就是套娃

隧道-内网穿透⭐

本地机器也可以通过CloudFlare隧道完成内网穿透

优点:

  • 支持代理http协议,提供SSL证书,自动升级https
  • 免费,基本无流量限制
    缺点:
  • 需要自定义域才能使用它的隧道服务(这是你的缺点)
  • 增加延迟(国内访问响应变慢)

开源的内网穿透方案:ftp,需要自行准备服务器搭建