解决
node-gyp报错、端口被占用、环境变量不对的那些破事
作为一名前端开发者,你是不是经常遇到这样的场景:
- 场景一:接手了一个三年前的 Vue2 项目,要求 Node.js 16 + npm 8。你看着自己电脑上刚装的 Node.js 22,内心一阵崩溃,跑起来全是报错。
- 场景二:项目终于跑起来了,上线部署到服务器,结果报错"缺少某某动态链接库",或者"GLIBC版本不匹配"。
这时候,你就需要Docker来救场了。
一、Docker 是什么?集装箱与万吨巨轮
官方说 Docker 是一个应用容器化工具。我们不必去死记硬背那些晦涩的定义。我们可以用一个比喻来理解:
- 传统开发:你在本地装好 Node、MySQL、Redis。这就像你在一艘船上到处堆满货物,换个船(服务器)就得重新搬一次。
- Docker 容器化 :Docker 就像海运的万吨巨轮 ,而每个容器就是一个标准集装箱。
核心公式:
Docker = 你的应用程序 + 它所需要的运行环境(Node版本、系统库等)
Docker 解决了什么问题?
解决了"在我的电脑上能跑,怎么在你电脑上就跑不起来了? "这个世纪难题。
二、Docker 核心概念:光盘(Image)与 DVD(Container)
刚开始接触 Docker,最容易搞混的就是 Image 和 Container。
| 概念 | 比喻 | 特点 |
|---|---|---|
| 镜像 (Image) | 光盘 | 只读的。包含了应用程序和运行环境的蓝图。你可以把它 push 到远程仓库(比如 Docker Hub)。 |
| 容器 (Container) | DVD 光盘 | 可运行 的。是镜像的一个实例。就像把光盘放进光驱播放,容器就是把镜像加载到内存里跑起来。 |
简单来说,我们通过 docker pull 拉取镜像(光盘),通过 docker run 运行镜像,生成容器(DVD)。
三、实战演练:Node.js + Nginx 部署全流程
为了彻底搞懂 Docker 的端口映射和配置挂载,我们来做一个极简的实战:用 Docker 启动一个 Nginx,反向代理到本地的 Node.js 服务。
1. 准备 Node.js 服务 (模拟后端)
首先,我们写一个最简单的 Node.js HTTP 服务,监听 1314 端口。
文件名:index.js
javascript
javascript
// 1. 引入 Node.js 原生 http 模块
const http = require('http');
// 2. 创建一个 HTTP 服务器
const server = http.createServer((req, res) => {
// 无论请求什么,都返回 Hello World
res.end('Hello Docker!');
});
// 3. 监听 1314 端口,0.0.0.0 表示监听所有网络接口
server.listen(1314, '0.0.0.0', () => {
console.log('Node server is running at http://localhost:1314/');
});
运行它:
bash
node index.js
访问 http://localhost:1314,你应该能看到 Hello Docker!。
2. 配置 Nginx (反向代理)
我们不直接访问 1314 端口(毕竟用户不会输入 :1314 来访问网站),而是通过 Nginx 监听默认的 80 端口,然后把请求转发给 Node 服务。
文件名:nginx.conf
nginx
ini
# nginx.conf 核心配置
# 1. Events 块:配置连接数等,一般保持默认
events {}
# 2. http 块:配置 HTTP 服务
http {
# 3. server 块:配置一个虚拟主机
server {
# 监听 80 端口
listen 80;
# 4. location 块:匹配根路径 /
location / {
# **重点**:反向代理!
# 将请求转发给 host.docker.internal:1314
# 注意:在 Docker for Mac/Windows 中,host.docker.internal 指向宿主机(你的电脑)
proxy_pass http://host.docker.internal:1314;
# 设置请求头,保持客户端真实 IP 等信息
proxy_set_header Host $host;
}
}
}
为什么要用
host.docker.internal?因为 Nginx 运行在 Docker 容器里,它不能直接访问
localhost:1314(容器的 localhost 指的是它自己)。我们需要通过这个特殊的域名告诉 Nginx:"去宿主机的 1314 端口找那个 Node 服务"。
3. 使用 Docker 运行 Nginx
现在,我们要把 Nginx 跑起来,并把我们刚才写的 nginx.conf 配置文件塞进去。
bash
perl
# 命令分解:
# docker run : 启动一个容器
# --name my-nginx : 给容器起个名字
# -p 80:80 : 端口映射。把宿主机的 80 端口映射到容器的 80 端口
# -v 配置文件路径:/etc/nginx/nginx.conf : 挂载卷。将本地的 nginx.conf 覆盖容器内的默认配置
# -d : 后台运行(detach 模式)
# nginx : 使用的镜像名称
docker run --name my-nginx-demo -p 80:80 -v C:\Users\你的用户名\Desktop\workspace\hhai\backend\docker\demo\nginx.conf:/etc/nginx/nginx.conf -d nginx
参数解析(非常重要):
-
-p 80:80:端口映射 。左边的80是你的电脑 (宿主机)端口,右边的80是容器内 Nginx 监听的端口。- 当你在浏览器输入
http://localhost(默认就是80端口),请求就会到达你电脑的80端口,然后 Docker 将其转发给容器的80端口。
- 当你在浏览器输入
-
-v:数据卷挂载 。这相当于把本地的文件"映射"进容器里。这里我们把本地的nginx.conf挂载到容器内的/etc/nginx/nginx.conf,替换掉默认配置。
4. 验证结果
执行上面的 docker run 命令后,打开浏览器访问 http://localhost(注意,是 80 端口,可以省略)。
如果一切顺利,你会看到 Node.js 输出的 Hello Docker! 。
流量走向回顾:
text
csharp
用户浏览器访问 localhost:80 (宿主机80端口)
↓ (端口映射 -p 80:80)
Docker 容器内的 Nginx 接收到请求 (容器内80端口)
↓ (Nginx 反向代理 proxy_pass)
Nginx 转发请求到 host.docker.internal:1314
↓ (Docker 网络桥接)
你电脑本机上运行的 Node.js 服务 (localhost:1314)
↓
Node.js 返回 "Hello Docker!"
↓ (原路返回)
浏览器展示页面
四、常用运维指令(建议收藏)
开发过程中,我们经常需要清理环境。这里整理了几个高频命令:
bash
makefile
# 1. 停止所有正在运行的容器
docker stop $(docker ps -q)
# 2. 删除所有已停止的容器(释放磁盘空间)
docker rm $(docker ps -aq)
# 3. 删除指定的镜像(比如删除 nginx 镜像)
docker rmi nginx
# 4. 拉取指定版本的 MySQL 镜像
docker pull mysql:8.0
# 5. 查看当前运行的容器列表
docker ps
# 6. 查看所有容器(包括已停止的)
docker ps -a
五、总结
通过这次实践,我们不仅了解了 Docker 的基本概念(镜像 vs 容器),还亲手搭建了一个 Node.js + Nginx 的反向代理环境。
核心要点回顾:
- Docker 容器 = 应用 + 运行环境,解决了环境不一致的问题。
- 镜像(Image) 是静态的"光盘",容器(Container) 是动态运行的"DVD"。
- 端口映射(-p) 是连接宿主机和容器的网络桥梁。
- 挂载(-v) 让修改配置文件变得像修改本地文件一样简单。
希望这篇文章能帮你迈过 Docker 入门的门槛。如果你在实践过程中遇到问题,欢迎在评论区交流讨论!