前端子包+docker流水线部署+nginx代理部署

文章目录

记录一次前端部署的子包的过程: 之前是前端项目打包成docker容器,暴漏出一个端口,在宿主机nginx中配置域名直接反向代理到前端的ip:端口项目。

现在的需求是加个后缀,因为业务的需要,比如原来是 aa.com访问,现在希望 aa.com/xxx 方式访问。

比如我现在想加个shop,通过aa.com/shop/访问,如何配置呢?

现在先给出原来的的代码,然后给出具体修改的地方

之前的部署文件

项目目录

Dockerfile

js 复制代码
FROM nginx:stable
MAINTAINER hufanglei

ADD default.conf /etc/nginx/conf.d/default.conf
COPY dist-prod/ /usr/share/nginx/html/

default.conf

js 复制代码
# 隐藏nginx版本
server_tokens off;

# 在某些浏览器上禁用内容类型嗅探。
add_header X-Content-Type-Options nosniff;

# 此标头启用跨站点脚本 (XSS) 过滤器
add_header X-XSS-Protection "1; mode=block";

# X-Frame-Options 是为了防止clickJacking攻击
# DENY:不允许在 frame 中展示#
# SAMEORIGIN:允许在相同域名下frame展示
# ALLOW-FROM https://example.com/ :指定来源的 frame 中展示
# add_header X-Frame-Options SAMEORIGIN;

# 开启gzip
gzip on;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;

# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,后面会有详细说明
gzip_comp_level 5;

# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;

# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;

# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";

# 设置压缩所需要的缓冲区大小
gzip_buffers 32 4k;

# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.0;

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
    # 带前缀方式的将 ${SERVER_NAME}替换为对应前缀名称即可,若访问直接在根目录下去掉${SERVER_NAME},去掉多余的/
    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;#根据官网这规则配置
        expires 5m;
    }



    # 若访问直接在根目录下,注释下面三行
    # location = / {
    #     return 301 $scheme://$host/organization/mgt;
    # }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

jenkinsfile

js 复制代码
def docker_image  //定义全局的镜像变量
def docker_image_name
pipeline {
    /*
    1.配置docker仓库相关变量 系统环境变量:DOCKER_REGISTRY_ADDR [docker仓库地址]
    credentials-[Username with password]类型:jenkins-docker-registry-creds[docker仓库账号/docker仓库密码]

    2.配置docker客户端访问的证书 系统环境变量:NAME_SPACE
    credentials-[X.509 Client Certificate]类型:jenkins-docker-client-creds[docker客户端凭证]

    合计:1个docker仓库地址环境变量,3个credentials为必须配置;
    `参考文档`:https://www.jenkins.io/zh/doc/book/pipeline/jenkinsfile
    `编写语法参考 `:http://groovy-lang.org/semantics.html
     */
    // 如果指定具体的节点执行,请 agent { label 'docker-slave' }
    agent any
    options {
        //超时一小时
        timeout(time: 1, unit: 'HOURS')
        //不允许同时执行
        disableConcurrentBuilds()
    }
// #######################需要修改的区域 开始#################################
    /**
     * 一般情况下只需要修改environment与parameters区域的
     */
    environment {
        // 服务的域名,一般与项目名称相同
        DOMAIN_NAME = 'xxxx'
        // 表示限制内存大小,单位为M,只能为数字;
        LIMIT_MEMORY = 2048
        // docker仓库地址,一般与系统环境变量相同,若相同时手动修改
        DOCKER_REGISTRY_ADDR = "${env.DOCKER_REGISTRY_ADDR}"
        // docker仓库账号密码--对应系统环境变量DOCKER_REGISTRY_ADDR
        DOCKER_REGISTRY = credentials('jenkins-docker-registry-creds')
        // 名称空间
        NAME_SPACE = 'jingke'
    }
    parameters {

        // 项目名称
        string(name: 'module', defaultValue: "xxx", description: '发布的项目')
        /* 以下4项参数需要配置到jenkins工程的参数中 */
        string(name: 'container_port', defaultValue: "49013", description: '容器端口')
        string(name: 'docker_remotes', defaultValue: "1.14.5.15", description: '远程docker的api地址列表,以","隔开')
        string(name: 'is_tls', defaultValue: "true", description: 'docker的api访问是否开启tls认证')
        // 服务部署扩展的环境变量,eg
        // choice(name: 'init_env', choices: ['-e APP_URL=htt://xxx '], description: '服务部署扩展的环境变量')
        /* 以下配置为jenkins工程必须设置 */
        // 配置Tag的git参数,参数类型 设置为 分支或标签
        // 配置git地址:在流水线 -> 定义[Pipeline script from SCM] -> SCM[git] -> Repository URL[git地址]
        // -> Credentials[git账号] -> 指定分支(为空时代表any)[${Tag}] --> 脚本路径[Jenkinsfile文件的工程路径]
        // -> 轻量级检出[去掉√ ]
    }
// ########################需要修改的区域 结束################################
    stages {
        stage('Run node') {
            agent {
                docker {
                    image 'node:20'
                    reuseNode true
                }
            }
            steps {
                sh "node -v && npm -v && npm config set registry https://registry.npmmirror.com && npm install && npm run build "
            }
        }

        stage('Build And Push Docker Image') {
            steps {
                script {
                    // 获取标签版本或者分支的commitId
                    if (!params.Tag || params.Tag.contains('origin/')) {
                        sh "git rev-parse --short HEAD > commit-id"
                        tag = readFile('commit-id').replace("\n", "").replace("\r", "")
                    } else {
                        tag = "$params.Tag"
                    }
                    // 赋值镜像名称
                    docker_image = "${env.DOCKER_REGISTRY_ADDR}/${name_space}/${params.module}-main:$tag"
                    docker_image_name = "${env.DOCKER_REGISTRY_ADDR}/${name_space}/${params.module}-main"
                    // 编译镜像
                    sh "rm -rf cicd/main/dist-prod && mv dist-prod cicd/main"
                    sh "docker build -t $docker_image cicd/main"
                }
                echo "完成DOCKER镜像打包......"
                sh "docker login ${DOCKER_REGISTRY_ADDR} --username=${DOCKER_REGISTRY_USR} --password=${DOCKER_REGISTRY_PSW}"
                sh "docker push $docker_image"
                sh "docker rmi $docker_image"
            }
        }
        stage('Deploy to docker') {
            environment {
                // docker客户端证书凭证,若不需要ssl访问则注释
                DOCKER_CERT_PATH = credentials('jenkins-docker-client-creds-hiband')
            }
            steps {
                script {
                    container_port = 80
                    container_port_map = ""
                    docker_client_env = ""
                    if (params.container_port) {
                        container_port = "${params.container_port}"
                        container_port_map = " -p ${params.container_port}:80 "
                    }
                    if (params.docker_remotes) {
                        def docker_remote_arr = "${params.docker_remotes}".split(",")

                        // 部署服务处理
                        for (int i = 0; i < docker_remote_arr.size(); ++i) {
                            docker_remote = "${docker_remote_arr[i]}"

                            docker_client_env = "export DOCKER_TLS_VERIFY=1; export DOCKER_HOST=tcp://${docker_remote}:2376; docker_remote=${docker_remote};"

                            sh "$docker_client_env docker rm -f $DOMAIN_NAME"

                            //部署服务
                            sh "$docker_client_env docker run -d --name ${DOMAIN_NAME} --restart=always \
                            -e TZ='Asia/Shanghai'  -e CONTAINER_PORT=${container_port} -m ${LIMIT_MEMORY}M \
                            $container_port_map -v /etc/localtime:/etc/localtime:ro   \
                            $docker_image"

                            echo "清理过时的镜像"
                            sh "$docker_client_env docker images $docker_image_name -q --filter before=$docker_image | xargs --no-run-if-empty docker rmi "

                        }
                    }
                }
            }
        }
    }
    post {
        always {
            echo '执行完成。'
            sh 'rm -rf .dockerignore'
        }
        success {
            echo '发布成功! please visit : https://aaa.com'
        }
        unstable {
            echo '发布不稳定哦...'
        }
        failure {
            echo '发布失败啦,请查明原因哦!'
        }
        changed {
            echo '与之前信息有所不同哦...'
        }
    }
}

前端的vite配置

java 复制代码
// https://vitejs.dev/config/
export default defineConfig(({command, mode}) => {
    const env = loadEnv(mode, process.cwd());

    return {
       ...
        root: process.cwd(),
        base: env.VITE_APP_BASE_URL || '/',
        resolve: {
            alias: {
                '@': resolve('src'),
                'assets': resolve('src/assets'),
            },
            extensions: ['.ts', '.js'],
        },
        ...

router.js

java 复制代码
...
const router = createRouter({
    history: createWebHistory(),
    routes,
})
...

宿主机的ngin配置

java 复制代码
server {
    listen       80;
    listen [::]:80;
    server_name  xx.com;
    server_tokens off;
    gzip on;
    gzip_static on;
    gzip_buffers 4 16k;
    gzip_comp_level 5;
    gzip_types text/plain application/javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;


    location / {
        return 301 https://$host$request_uri;
    }
  
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}



# hiband 443
server {
    listen 443 ssl;
    server_name xx.com;

    server_tokens off;

    ssl_certificate /xxx/cert.crt;
    ssl_certificate_key /xxx/cert.key;

    ssl_session_timeout 5m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;

#    root /usr/share/nginx/html/aisprint-pro-online-main;    

    location / {
#     try_files $uri $uri/ /index.html;
      proxy_pass http://x.x.x.x:49013/;
    }


    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root html;
    }
}

修改后的代码

Dockerfile

js 复制代码
FROM nginx:stable
MAINTAINER hufanglei

ADD default.conf /etc/nginx/conf.d/default.conf
#COPY dist-prod/ /usr/share/nginx/html/
RUN mkdir -p /usr/share/nginx/html/shop
COPY dist-prod/ /usr/share/nginx/html/shop/

jenkinsfile不用变

容器内的dockerfile

js 复制代码
erver {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;
    # 带前缀方式的将 ${SERVER_NAME}替换为对应前缀名称即可,若访问直接在根目录下去掉${SERVER_NAME},去掉多余的/
    location /hstub/ {
        alias /usr/share/nginx/html/shop/;
        index index.html;
        try_files $uri $uri/ /shop/index.html;#根据官网这规则配置
        expires 5m;
    }

前端vite

js 复制代码
export default defineConfig(({command, mode}) => {
    const env = loadEnv(mode, process.cwd());

    return {
        plugins: [vue(),
          ...
        ],
        root: process.cwd(),
        // 关键代码
        base:  '/shop/',
        ...

router.js

java 复制代码
const router = createRouter({
    history: createWebHistory("shop"),
    routes,
})

宿主机的ngin配置

java 复制代码
erver {
    listen 443 ssl;
    server_name xx.com;

      ....


    location /shop/ {
        proxy_pass http://xxx:49014/shop/;
        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;
    }

总结

Vite 前端源码

│ build

dist-prod/\] ← 打包输出(base: /shop/) │ ▼ \[Docker 镜像构建\] → Docker 内 nginx │ RUN mkdir -p /usr/share/nginx/html/shop ▼ \[容器内 nginx 服务

│ proxy_pass

宿主机 nginx\] → 外网访问 > 说明: > Vite 打包生成 /dist-prod(JS/CSS + index.html),资源路径自动加 /shop/ > > Dockerfile 内部创建 /shop 目录并拷贝 dist > > Docker 内 nginx 根据 /shop / 规则 serve SPA\>宿主机 nginx 根据 location /shop / 转发到容器 IP:PORT > > 浏览器访问 /shop/→ nginx → Docker nginx → 前端资源 *** ** * ** *** 大功告成!

相关推荐
Java程序员威哥2 小时前
云原生Java应用优化实战:资源限制+JVM参数调优,容器启动快50%
java·开发语言·jvm·python·docker·云原生
大房身镇、王师傅2 小时前
【Docker】RockyLinux10 安装 docker-compose
运维·docker·容器·docker-compose·rockylinux10
0思必得02 小时前
[Web自动化] Selenium浏览器对象属性
前端·python·selenium·自动化·web自动化
小二·2 小时前
Python Web 开发进阶实战:边缘智能网关 —— 在 Flask + Vue 中构建轻量级 IoT 边缘计算平台
前端·python·flask
是毛毛吧2 小时前
GitHub热榜----前端已死?AionUi 横空出世:首个开源“生成式UI”框架,让 AI 在运行时“手搓”界面
前端·开源·github
斯普信专业组2 小时前
ReAct Agent 解析:从理论到实践的高效推理框架
前端·react.js·前端框架
徐同保2 小时前
开发onlyoffice插件,功能是选择文本后立即通知父页面
开发语言·前端·javascript
23124_802 小时前
Base64多层嵌套解码
前端·javascript·数据库
多看书少吃饭2 小时前
文件预览的正确做法:从第三方依赖到企业级自建方案(Vue + Java 实战)
java·前端·vue.js