当前位置: 首页 > news >正文

Docker+Nginx+Node.js实战教程:从零搭建高可用的前后端分离项目

更多云服务器知识,尽在hostol.com

你是否已经掌握了Nginx的“交通指挥术”?是否也学会了Docker的“集装箱打包法”?是否对Node.js的后端开发跃跃欲试?

很好。今天,我们将把这三大“王牌军”——Nginx、Docker、Node.js——整合在一起,从一张白纸开始,亲手构建一个在现代Web世界中最经典、最实用、也最能体现你专业水准的“作战队形”——一个高可用的、前后端分离的项目

这篇文章会很长,很深入,细节会很多。但请跟紧我的步伐。完成这次演习后,你将不再是一个只会使用单个工具的“士兵”,你将晋升为一个懂得如何排兵布阵、构建稳健体系的“战场指挥官”。


“作战蓝图”:我们要建造一个什么样的“餐厅”?

在开工前,我们先来理清我们的“作战蓝图”。我们要搭建的是一个前后端分离的应用。让我们用一个“开餐厅”的比喻来理解它:

  • 后端 (Backend): 这是我们的“厨房”。我们将用Node.js来打造这个厨房,它负责处理所有核心的“烹饪”工作(业务逻辑、数据处理)。
  • 前端 (Frontend): 这是我们的“餐厅大堂”。我们将用一个纯静态的HTML+JS页面来构建,它只负责“展示菜品”和“接待顾客”(界面UI和用户交互)。
  • Nginx: 这是我们餐厅的“大堂经理兼总调度”。他负责两件大事:
    1. 将顾客直接引导到“餐厅大堂”(处理前端静态页面的访问)。
    2. 将顾客点的“菜单”(API请求),准确无误地传递给“厨房”(后端服务),并将做好的“菜品”(数据)端回给顾客。
  • Docker: 这是我们用来建造和管理“厨房”和“大堂”的“标准化施工队”。我们将把前端和后端,分别打包成独立的、标准化的“集装箱”,确保它们能在任何地方,以同样的方式完美运行。
  • 高可用 (High Availability): 这是本次演习的“进阶科目”。我们不只建一个“厨房”,我们要建两个一模一样的厨房!如果其中一个厨房突然“煤气泄漏”(服务器宕机),我们的“大堂经理”Nginx,会自动、无缝地,将所有菜单都转交给另一个健康的厨房。顾客甚至都不知道刚才后厨发生了一场危机。

蓝图清晰了?很好,指挥官,请下达开工指令!

第一阶段:建造“厨房”——我们的Node.js API后端

我们先来构建负责核心业务的“厨房”。

  1. 创建项目目录并准备“食材” (package.json) 在你的本地电脑上,创建一个项目文件夹,比如my-project,然后在里面创建一个backend文件夹。

Bash

mkdir -p my-project/backend
cd my-project/backend

backend目录里,创建一个package.json文件,告诉Node.js我们的项目需要什么“配料”(依赖):

JSON

{"name": "backend","version": "1.0.0","main": "server.js","scripts": {"start": "node server.js"},"dependencies": {"express": "^4.18.1"}
}

2编写“菜谱” (server.js) 创建一个server.js文件,这是我们厨房的核心“主厨”,负责烹饪一道简单的“招牌菜”:

JavaScript

const express = require('express');
const app = express();
const PORT = 3000;
const HOSTNAME = require('os').hostname(); // 获取主机名,用于区分不同容器app.get('/api/status', (req, res) => {res.json({message: 'Hello from the Backend!',serverHost: HOSTNAME // 返回当前是哪个“厨房”在为您服务});
});app.listen(PORT, '0.0.0.0', () => {console.log(`Backend server is running on host ${HOSTNAME}, port ${PORT}`);
});

这个API很简单,当访问/api/status时,它会返回一条信息,并告诉我们是哪个“厨房”(容器)处理了这次请求。

3为“厨房”撰写“建造说明书” (Dockerfile)backend目录下,创建Dockerfile

Dockerfile

# 使用一个轻量级的Node.js环境作为“厨房地基”
FROM node:18-alpine# 在厨房里,创建一个叫/app的操作台
WORKDIR /app# 把“食材清单”复制进去
COPY package*.json ./# 根据清单,自动“采购食材”
RUN npm install# 把所有“菜谱”都复制进去
COPY . .# 声明这个厨房的“出餐口”在3000
EXPOSE 3000# 规定厨房的开工命令
CMD [ "npm", "start" ]

  1. 这份说明书,详细地记录了如何一步步地,将我们的Node.js应用,打包成一个标准化的Docker“厨房集装箱”。

第二阶段:装修“餐厅大堂”——我们的静态前端

厨房建好了,我们来装修门面。

  1. 创建前端目录和“菜单” (index.html)

my-project下,创建frontend文件夹,并在里面创建一个index.html文件。

Bash

cd ../frontend
nano index.html

写入以下内容:

HTML

<!DOCTYPE html>
<html>
<head><title>前后端分离项目</title><style>body { font-family: sans-serif; text-align: center; margin-top: 50px; }button { font-size: 1.2em; padding: 10px 20px; }#status { margin-top: 20px; font-weight: bold; }</style>
</head>
<body><h1>欢迎来到我的应用!</h1><button onclick="fetchStatus()">点击我,从后端获取状态</button><div id="status"></div><script>function fetchStatus() {const statusDiv = document.getElementById('status');statusDiv.innerText = '正在获取...';fetch('/api/status') // 注意!这里直接请求相对路径.then(response => response.json()).then(data => {statusDiv.innerText = `消息: ${data.message} \n (由厨房 ${data.serverHost} 提供服务)`;}).catch(error => {statusDiv.innerText = '获取失败!请检查后端服务。';console.error('Error:', error);});}</script>
</body>
</html>

这个页面很简单,只有一个按钮。点击它,它会通过JavaScript的fetch函数,去请求我们后端的/api/status接口,并把返回的结果,显示在页面上。

第三阶段:召唤“总包工头”——用docker-compose编排一切

现在,我们有了“厨房”和“大堂”的图纸,但我们需要一个“总包工头”,来把它们一起建造并连接起来。这个角色,由docker-compose来扮演。

在你的项目根目录my-project下,创建docker-compose.yml文件。

YAML

version: '3.8'services:# --- 后厨部门 ---backend:build: ./backend  # 使用backend目录下的Dockerfile来建造deploy:replicas: 2     # 魔法在这里!告诉总包工头,给我一模一样地建“两间”厨房networks:- my-app-network# --- 前厅与总调度 ---nginx:image: nginx:alpineports:- "80:80"       # 将我们服务器的80端口,映射到Nginx容器的80端口volumes:- ./frontend:/usr/share/nginx/html  # 将我们的“餐厅大堂”文件,挂载到Nginx的网站目录- ./nginx.conf:/etc/nginx/nginx.conf # 将我们的“大堂经理工作手册”,挂载到Nginx的配置目录depends_on:- backendnetworks:- my-app-networknetworks:my-app-network:driver: bridge

这份docker-compose.yml,就是我们的总施工蓝图。它定义了我们需要建造的两个服务(backendnginx),以及它们之间的关系。

第四阶段:撰写“大堂经理”的终极工作手册 (nginx.conf)

最后,我们需要为Nginx这位“大堂经理”,撰写一份清晰的工作手册,告诉它如何接待客人和传达菜单。

在项目根目录my-project下,创建nginx.conf文件。

Nginx

events {}http {# 定义我们的“后厨小组”upstream backend_servers {# Docker Compose会自动将backend这个名字,解析到我们那两个厨房容器的IP上# 它会自动在这两者之间,进行轮询负载均衡server backend:3000;}server {listen 80;# 如果客人是直接访问首页location / {root   /usr/share/nginx/html;index  index.html;try_files $uri $uri/ =404;}# 如果客人的请求路径,是以/api/开头的(点菜)location /api/ {# 就把这个菜单,转交给“后厨小组”去处理proxy_pass http://backend_servers;proxy_set_header Host $host;# ... 此处省略其他几行proxy_set_header...}}
}

这份配置,完美地实现了我们“前后端分离”和“负载均衡”的目标。

发射!——启动你的“商业帝国”

好了,所有的蓝图和说明书,都已准备就绪。

现在,SSH登录到你那台已经装好了Docker和Docker Compose的腾讯云轻量服务器上。把你的整个my-project文件夹,上传到服务器。

进入项目目录,然后,念出那句最激动人心的咒语:

Bash

sudo docker-compose up --build -d

-d表示在后台运行。

Docker Compose这位“总包工头”,会开始阅读你的蓝图,自动地:

  1. 建造你的“餐厅大堂”(拉取Nginx镜像)。
  2. 建造你的两间一模一样的“厨房”(根据Dockerfile构建后端镜像,并启动两个容器)。
  3. 建立它们之间的内部“高速网络”。
  4. 启动Nginx“大堂经理”,并让他按照你的手册开始工作。

最后的检阅: 打开你的浏览器,访问你服务器的公网IP地址。你会看到那个简洁的前端页面。

现在,反复点击那个按钮!你会看到,页面上显示的“由厨房 ... 提供服务”后面的那个主机名,在不断地变化

这意味着,Nginx这位大堂经理,正在完美地,将你的每一次“点菜”请求,轮流地、平均地,分发给我们那两间健康的“厨房”!我们的“高可用”架构,成功了!

你,已是“全栈指挥官”

看看你的成果。你不再只是一个会做一道菜的“厨师”,或者一个只会迎宾的“服务员”。你成了一位能设计出整个餐厅的复杂动线、并让它高效、稳定、且具备容灾能力运转的“餐厅总设计师”(全栈工程师/DevOps)。

你亲手指挥了一场漂亮的多兵种协同作战。这,就是现代Web开发的艺术。它关乎分离,也关乎协作;关乎性能,也关乎稳定。

现在,去为你的下一个伟大创意,设计一套更宏伟、更可靠的“作战蓝图”吧。

http://www.lryc.cn/news/625645.html

相关文章:

  • 黑客哲学之学习笔记系列(六)
  • Node.js完整安装配置指南(包含国内镜像配置)
  • HTB 赛季8靶场 - CodeTwo
  • HarmonyOS 实战:学会在鸿蒙中使用第三方 JavaScript 库(附完整 Demo)
  • 土地财政历史探寻
  • 陪诊系统开发哪家强?XK+支持 API对接+私有化部署,按需定制功能模块!
  • 涡流-信号完整性分析
  • 软件开发中的 8 个伦理问题示例
  • KMM跨平台叛逃实录:SwiftUI与Compose Multiplatform共享ViewModel的混合开发框架(代码复用率85%)
  • MySQL事务篇-事务概念、并发事务问题、隔离级别
  • 微软AD国产化替换倒计时——不是选择题,而是生存题
  • 【python实用小脚本-190】Python一键删除PDF任意页:输入页码秒出干净文件——再也不用在线裁剪排队
  • 《WASM驱动本地PDF与Excel预览组件的深度实践》
  • LeetCode 100 -- Day2
  • Leetcode 3654. Minimum Sum After Divisible Sum Deletions
  • C++小游戏NO.1游戏机
  • 【GNSS定位原理及算法杂记5】​​​​PPK(后处理动态定位)深度解析:后处理的艺术与 RTK 的互补
  • 【HarmonyOS】H5 实现在浏览器中正常跳转 AppLinking 至应用
  • HarmonyOS 中的 setInterval的基本使用
  • Android Coil 3拦截器Interceptor计算单次请求耗时,Kotlin
  • 进程通信:进程池的实现
  • Java 大视界 -- Java 大数据在智能物流无人配送车路径规划与协同调度中的应用
  • 【什么是非晶合金?非晶电机有什么优点?】
  • k8sday11服务发现(2/2)
  • Kubernetes 的 YAML 配置文件-kind
  • 在 Kotlin 中 使用泛型类和泛型函数
  • WRC大会精彩回顾 | NanoLoong机器人足球首秀青龙机械臂咖啡服务双线出击
  • 【论文阅读】DETR3D: 3D Object Detection from Multi-view Images via 3D-to-2D Queries
  • 【新启航】航空飞机起落架深孔型腔的内轮廓检测方法探究 - 激光频率梳 3D 轮廓检测
  • 主流 3D 模型格式(FBX/OBJ/DAE/GLTF)材质支持与转换操作指南