前端不懂 Docker ?先用它换掉常规的 Vue 项目部署方式

本项目代码已开源,具体见:

前端工程:vue3-ts-blog-frontend

后端工程:express-blog-backend

数据库初始化脚本:关注公众号程序员白彬,回复关键字“博客数据库脚本”,即可获取。

为什么需要容器化

当一个项目越来越复杂时,或者部署的环境越来越复杂时,你可能会考虑使用容器化部署来交付项目。因为你必须要考虑这样一些问题:

  • 为什么这个项目在我本地是正常的,部署到生产环境就不正常了?
  • 生产服务器要部署两个 nodejs 项目,但是这两个项目依赖的 nodejs 版本不一样,怎么办?
  • 买了一台新的云服务器,把项目从旧服务器迁移过去就跑不起来了…
  • 服务器部署了两个项目,但是其中一个项目误修改了另一个项目的一些关联文件,导致程序崩溃…

这些都是生产实践中会发生的问题,容器化的出现就是为了解决这些问题。

前端开发不懂容器化很正常,因为我们平时工作很难接触到这些。没关系,我们要创造机会让自己学会它,至少要让自己了解它。

简单认识 Docker

学习容器化肯定离不开 Docker,我们首先要对 Docker 的基础概念有所认识,这些可以去看Docker 官方文档学习,我也花了挺多时间去看文档,这是了解第一手信息最好的方式。

我一直推崇通过官方文档学习,因为这几乎就是最权威的资料。有了这些信息,再翻到一些文章或博客时,对一些观点也能有自己的判断力。

  • Image
  • Container
  • Network
  • Volume

Image 就是镜像,相当于一个类,或者说是一个模板,Image 是通过 Dockerfile 定义和构建的,Dockerfile 描述了制作 Image 的过程。

Container 是容器,它是基于镜像实例化得到的。容器是天然隔离的,容器包含了运行应用程序所需的所有东西,比如代码、依赖库、环境变量等。

Network 是网络,允许容器之间以及容器与宿主机之间进行通信。

Volume 是数据卷,用于挂载文件,解决容器中文件持久化的问题。

Docker 采用经典的CS架构。我们用 Docker Desktop 也好,用命令行也好,都是相当于一个客户端,我们给出的指令,首先会被 Docker daemon 接收,daemon 就是一个监视器进程,相当于一个守门员,所有的指令都要经过它的调度才能被处理,比如镜像操作、容器操作、网络操作、卷操作等等。

image.png

将 Vue 项目做成 Docker 镜像

我们在前端上手全栈自动化部署,让你看起来像个“高手”这篇文章中提到过,整个项目的部署架构是这样的:

image.png

在我们使用容器化改造全栈博客项目时,可以循序渐进,不必整个前后端全部都容器化,可以先把 Vue 前端部分换掉,也不会影响整个系统架构。我们来试着做一下。

image.png

前端项目一般都会用到框架,需要打包后才能交给服务器部署,所以第一步是打包,打包需要一个 NodeJS 环境。下面就是打包相关的 Dockerfile 配置。

# 使用官方Node.js作为基础镜像
FROM node:16 as builder# 设置工作目录
WORKDIR /app# 首先复制项目的依赖配置文件
COPY package.json yarn.lock ./# 安装项目依赖,这一步会生成一个独立的层,并且只有在package.json或yarn.lock变化时才会重新执行
RUN yarn install# 接着复制项目所有文件,这一步会生成一个新的层
COPY . .# 构建项目,这一步也会生成一个新的层
RUN yarn build

前端打包后就会得到一堆静态文件,包括 html, js, css, 图片、音频、视频等。

那么怎么让用户访问到网站的这些前端资源呢?这就需要一个 Web 服务器。

Nginx 就可以充当这个 Web 服务器,最后需要把端口暴露出去,并且安全组要放行该端口,不然是没法通过网络访问的。

# 使用Nginx镜像来运行构建好的项目
FROM nginx:latest# 将构建好的项目复制到Nginx镜像的/usr/share/nginx/html目录下
COPY --from=builder /app/dist/ /usr/share/nginx/html# 暴露端口
EXPOSE 80

整合上面的 Dockerfile 后,我们就可以执行打镜像的命令了。

docker build -t vue3-ts-blog-frontend .

最后的.号代表上下文路径,Docker 会在这个路径下寻找 Dockerfile 及其他文件,根据 Dockerfile 配置打镜像。

image.png

打镜像成功后,可以在本地运行一下这个镜像进行验证。

docker run -dp 3000:80 vue3-ts-blog-frontend

3000:80代表把宿主机的 3000 端口转发到容器的 80 端口,vue3-ts-blog-frontend则是我们刚才打出的镜像的名字。

接着我们打开http://localhost:3000访问,发现前端界面显示出来了,但是接口访问是404。

image.png

而且可以看到,接口的访问路径是这样的:

http://localhost:3000/article/page?pageNo=1&pageSize=6

按道理应该有/api前缀的,因为我们用环境变量配置了 axios 的 baseURL。

image.png

我们知道,webpack 在打包阶段会将process.env.VUE_APP_BASE_API的值替换成对应的字符串。本地 yarn build 会得到这样的结果。

image.png

这说明是镜像构建的时候出了问题,导致VUE_APP_BASE_API没生效。我看了一下容器运行时的文件,找到了对应的 js 文件,发现这个对象里压根没有VUE_APP_BASE_API

image.png

最后费了老大劲发现是 docker 默认模板生成的 .dockerignore 文件把我给坑了,它忽略了 .env,这就导致了打包时找不到 VUE_APP_BASE_API 这个环境变量,真是服了!

image.png

修改 .dockerignore 之后重新打镜像,运行容器,/api 的访问路径也正常了。虽然 /api 访问得到的结果是 404 Not Found,但是路径已经对了。后端服务是 404 可以先不管,后面用 nginx 转发一下就行。

image.png

此时我们还要做一点事情,那就是 404 的 fallback 处理,这个需要通过 nginx 的 try_files 配置实现。

如果不做任何处理,随便输入一个不存在的路由会被 nginx 返回 404,这是 nginx 默认的 404 页面。但是我们通常希望如果用户随便输入一个路由,应该给一个友好的 404 界面,这个工作可以由 nginx 承接,我们可以修改 nginx 默认的 404 页面;这个工作也可以由前端来承接,将流量转发到前端即可,再由前端路由到 /404。

image.png

想要让 /not-found-route 这种找不到的路由最终能被前端处理,就需要一个 try_files 配置。

如果要给 nginx 配置 try_files,就需要覆盖 nginx 镜像的 /etc/nginx/conf.d/default.conf 文件,我们给 Dockerfile 新增一条 COPY 指令。

# 复制自定义的Nginx配置到镜像中,覆盖默认配置
COPY nginx/default.conf /etc/nginx/conf.d/default.conf

接着我们在项目中新建一个 nginx/default.conf 文件,配置内容也很简单。

server {listen 80;root /usr/share/nginx/html;index index.html;location / {try_files $uri $uri/ /index.html;}
}

有了 try_files 配置后,无法匹配 nginx 路由的请求就会被转到 index.html,这个 index.html 自然就是 Vue 项目的入口。如果项目中 vue-router 配置了pathMatch,就能将未被定义的路由重定向到 /404 路由。

// 匹配任意路径
const FALLBACK_ROUTE = {name: "Fallback",path: "/:pathMatch(.*)*",redirect: "/404",
}

image.png

此时这个镜像的准备工作就算是完成了,可以重新打包镜像。

docker build -t vue3-ts-blog-frontend .

此时可能有朋友脑子里还记得接口访问 404 的问题,没关系,这个会在镜像部署到服务器后解决。我们先接着往下看,不着急。

私有镜像仓库的使用

镜像打好了之后,总得有个地方把它存起来,然后服务器上才能去拉取这个镜像进行部署,这就是镜像仓库做的事情。

镜像仓库有私有的,也有公开的,对于个人项目,我们通常希望使用私有镜像仓库。但是 DockerHub 官方对于未付费用户进行了限制,对单账号只提供一个私有仓库名额,这显然是不够用的。

DockerHub 上有一个 registry 镜像,就是用来搭建镜像仓库的。后续抽空单独出一篇文章分享一下如何用这个 registry 镜像搭建一个私有 Docker Registry。

既然先不着急搭建私有镜像仓库,我们就寻找一个免费的可靠的私有镜像仓库提供商,aliyun 就提供了这个能力。

我们打开 aliyun 控制台,在容器-容器服务这里有个容器镜像服务 ACR,我们打开它。

image.png

目前,aliyun 对个人用户提供了 300 个仓库的免费额度,这完全是够用的,我们用它来搭建自己的私有镜像仓库完全足够!

image.png

我们按照指引创建命名空间和仓库后,就可以进入仓库查看了,这里提供了登录 registry、推拉镜像的所有命令示例,操作起来非常简单。

image.png

私有镜像仓库都是要先登录才能使用的,我们先用 docker login 登录 aliyun registry。

docker login --username=itaobao8023 registry.cn-hangzhou.aliyuncs.com
Password: 
Login Succeeded

然后使用 docker tag 给前端项目打一个 aliyun registry 专属的 tag。

docker tag vue3-ts-blog-frontend registry.cn-hangzhou.aliyuncs.com/tusi_personal/blog:2.0.4

接着就可以使用 docker push 推送镜像了。

docker push registry.cn-hangzhou.aliyuncs.com/tusi_personal/blog:2.0.4

服务器部署改造

接着我们来到服务器,在服务器上拉取这个镜像。当然在服务器上也要先登录,才能 pull 镜像,我们先执行上面的 docker login 操作。

接着进行 pull 操作拉取镜像。

docker pull registry.cn-hangzhou.aliyuncs.com/tusi_personal/blog:2.0.4

镜像拉取成功后,通过 docker run 把容器跑起来。

docker run -dp 3000:80 registry.cn-hangzhou.aliyuncs.com/tusi_personal/blog:2.0.4

容器的 80 端口映射到了宿主机器的 3000 端口,此时可以通过 curl 测试一下可访问性。

curl localhost:3000

如果能看到下面的结果,说明容器运行没有异常。

image.png

不过此时仅仅是把 Vue 项目的 nginx 容器跑起来了,整个博客项目的部署架构还没有调整呢。我们再回顾一下这张部署架构图,然后思考一下怎么改造它。

image.png

我们知道,整个博客是通过 nginx 接入的,/api 和 /socket.io 前缀的流量会转发到 express backend 服务,其余流量会到 /usr/share/nginx/html/vue3-ts-blog-frontend 这个目录下,也就是访问前端的静态资源文件。我们要改变这个行为,让除 /api 和 /socket.io 之外的流量全部转发到我们的前端容器中,这个容器目前是通过 3000 端口访问的。

/api 是用来访问后端 API 接口的,/socket.io 开头的请求是 Socket.IO 相关的。这些都不是前端的范畴,所以要转发到后端。

按照这个部署逻辑,我们修改一下 nginx 配置文件。

server {listen	80 default_server;server_name _;return 403;
}server {listen       80;server_name  blog.wbjiang.cn;rewrite ^(.*)$ https://$server_name$1 permanent;
}#博客https
server {listen 443 ssl http2;server_name blog.wbjiang.cn;ssl_certificate  /etc/nginx/cert/blog.wbjiang.cn.pem;ssl_certificate_key  /etc/nginx/cert/blog.wbjiang.cn.key;ssl_session_timeout 5m;ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;ssl_prefer_server_ciphers on;location / {proxy_pass http://localhost:3000;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;}#api转发location /api {proxy_pass http://blog_pool;proxy_http_version 1.1;proxy_set_header Host $host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;rewrite ^/api/(.*)$ /$1 break;}#websocket转发location /socket.io {proxy_pass http://blog_pool;proxy_http_version 1.1;proxy_set_header Host $host;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";}
}

注意上面的 location / 规则,它就是把默认流量转发到了 localhost:3000,也就是我们用 docker 运行的前端 nginx 容器。这样一来,整个系统的部署架构就变成了下面这样。

image.png

最后只需要重启 nginx 服务即可。

nginx -s reload

小结

我们希望在本项目中学习 docker 的使用,但是又不希望破坏整个系统的部署架构,因此做了这样的设计,只针对 vue 前端部分采用了 docker 部署方式。通过实践,我们学会了如何使用 docker 制作镜像、运行容器、上传镜像,也学会了怎么使用私有镜像仓库,最终在完全兼容的前提下成功改造了系统的部署方式。不过,我们还仅仅是跑通了部署流程,未曾修改 CI/CD 配置,这个后续再做分享。

  • 开源地址:vue3-ts-blog-frontend
  • 专栏导航:Vue3+TS+Node打造个人博客(总览篇)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/380190.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在 Mac 上下载安装植物大战僵尸杂交版? 最新版本 2.2 详细安装运行教程问题详解

植物大战僵尸杂交版已经更新至2.2了,但作者只支持 Windows、手机等版本并没有支持 MAC 版本,最近搞到了一个最新的杂交 2.2 版本的可以在 Macbook 上安装运行的移植安装包,试了一下非常完美能够正常在 MAC 上安装运行,看图&#x…

Linux云计算 |【第一阶段】ENGINEER-DAY5

主要内容: SELinux、系统故障修复、HTTPD/FTP服务搭建、防火墙策略管理、服务管理 一、SELinux安全制度 SELinux(Security-Enhanced Linux),美国NSA国家安全局主导开发,一套增强Linux系统安全的强制访问控制体系&…

大模型只是轮子,与其闭门重复造轮子,不如深耕场景应用

如何理解李彦宏说的“不要卷模型,要卷应用” 7月4日,2024世界人工智能大会暨人工智能全球治理高级别会议全体会议在上海世博中心举办。在产业发展主论坛上,百度创始人、董事长兼首席执行官李彦宏呼吁:“大家不要卷模型&#xff0…

JavaWeb JavaScript ① JS简介

目录 一、HTML&CSS&JavaScript的作用 二、前后端关联标签——表单标签 1.form标签 2.input标签 3.get/post提交的差异 4.表单项标签 5.布局相关标签 块元素——div 行内元素——span 三、CSS 1.CSS引入方式 方式1 行内式 方式2 内嵌式 方式3 外部样式表 2.CSS选择器 元…

第三届智能机械与人机交互技术学术会议(IHCIT 2024)

【北航主办丨本届SPIE独立出版丨已确认ISSN号】 第三届智能机械与人机交互技术学术会议(IHCIT 2024) 2024 3rd International Conference on Intelligent Mechanical and Human-Computer Interaction Technology 2024年7月27日----中国杭州&#xff0…

Artix7系列FPGA实现SDI视频编解码,基于GTP高速接口,提供3套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案在Xilinx--Kintex系列FPGA上的应用本方案在Xilinx--Zynq系列FPGA上的应用 3、详细设计方案设计原理框图SDI 输入设备Gv8601a 均衡器GTP 高速接口-->解串与串化SMPTE SD/HD/3G SDI IP核BT1120转…

Python+Flask+MySQL/Sqlite的个人博客系统(前台+后端管理)【附源码,运行简单】

PythonFlaskMySQL/Sqlite的个人博客系统(前台后端管理)【附源码,运行简单】 总览 1、《个人博客系统》1.1 方案设计说明书设计目标工具列表 2、详细设计2.1 管理员登录2.2 程序主页面2.3 笔记新增界面2.4 文章新增界面2.5 文章/笔记管理界面2…

实战:Eureka的概念作用以及用法详解

概叙 什么是Eureka? Netflix Eureka 是一款由 Netflix 开源的基于 REST 服务的注册中心,用于提供服务发现功能。Spring Cloud Eureka 是 Spring Cloud Netflix 微服务套件的一部分,基于 Netflix Eureka 进行了二次封装,主要负责…

C/C++ json库

文章目录 一、介绍1.1 json 介绍 二、C/C json 库选型2.1 选型范围2.2 jsoncpp2.2.2 jsoncpp 编译和交叉编译 2.3 rapidjson2.4 nlohmann/json2.5 sonic-cpp 五、常见问题5.1 jsoncpp 中关于浮点数的控制和中文显示问题5.2 jsoncpp序列化double类型时精度损失问题的解决办法 一…

docker 部署wechatbot-webhook 并获取接口实现微信群图片自动保存到chevereto图库等

功能如图: docker部署 version: "3" services:excalidraw:image: dannicool/docker-wechatbot-webhook:latestcontainer_name: wechatbot-webhookdeploy:resources:limits:cpus: 0.15memory: 500Mreservations:cpus: 0.05memory: 80Mrestart: alwayspor…

「实战应用」如何用DHTMLX将上下文菜单集成到JavaScript甘特图中(三)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求,是最完善的甘特图图表库。 DHTMLX Gantt是一个高度可定制的工具,可以与项目管理应用程序所需的其他功能相补充。在本文中您将学习如何使用自定义上…

React、Vue的password输入框组件,如何关闭自动填充?

有时候我们的表单使用了一个password组件,这时候每次打开新建,都会自动获取浏览器缓存的密码,但是它的上一个input输入框并不是用户名,这时候我们希望我们的表单,每次点开的时候密码是空的,让用户自动输入&…

iMazing 3 换手机后苹果游戏数据还有吗 换iPhone怎么转移游戏数据

当你想要更换手机,无论是选择升级到最新款iPhone,或者换到“经典”旧款iPhone,单机游戏数据的转移总是让人发愁。本文将详细介绍换手机后苹果游戏数据还有吗,以及换iPhone怎么转移游戏数据,确保你能无缝继续你的游戏体…

【体外诊断】ARM/X86+FPGA嵌入式计算机在免疫分析设备中的应用

体外诊断 信迈提供基于Intel平台、AMD平台、NXP平台的核心板、2.5寸主板、Mini-ITX主板、4寸主板、PICO-ITX主板,以及嵌入式准系统等计算机硬件。产品支持GAHDMI等独立双显,提供丰富串口、USB、GPIO、PCIe扩展接口等I/O接口,扩展性强&#xf…

源码搭建国内微短剧系统(小程序+APP)短剧配置抖音教程

短剧不知道如何配置抖音小程序?翻阅很多资料帮大家整理了一份非常详细的操作文档,给大家介绍源码搭建的短剧系统是如何一步一步配置抖音小程序的。 顺便推荐一下他们的开源地址:https://gitee.com/nymaite_com_2878868888/tjguonei 文档说明…

# Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型

Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型 一、redis 服务器配置–redis.conf 配置 1、服务器端设定 1)设置服务器以守护进程的方式运行: daemonize yes|no 2)绑定主机地址: bin…

NVIDIA全面转向开源GPU内核模块

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

199.二叉树的右视图(DFS)

给定一个二叉树的根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3: 输入: [] 输出: [] 解题…

“生日悖论”简析——公式计算、代码模拟

“生日悖论”共享生日概率,通项公式计算,代码模拟计算。 (笔记模板由python脚本于2024年07月17日 18:16:40创建,本篇笔记适合会基础编程的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free&…

ranger审计日志对接CDH solr

作者:耀灵 一、准备条件 1、已安装完毕ranger-admin 2、已在CDH上部署solr(注意在安装solr时更改下solr在zk上的节点信息) 二、更改相关配置 1、修改ranger-2.1.0-admin/contrib/solr_for_audit_setup/install.properties SOLR_USERsolr …