前端开发必会的Docker实战:从“我电脑能跑”到“轻松部署”

15 阅读4分钟

解决 node-gyp 报错、端口被占用、环境变量不对 的那些破事。
本文涵盖:Node.js 服务、Nginx 反向代理、MySQL 容器化部署,一套组合拳打通本地开发环境。


一、Docker 是什么?集装箱与万吨巨轮

官方说 Docker 是一个应用容器化工具。我们不必死记硬背那些晦涩的定义,可以用一个比喻来理解:

  • 传统开发:你在本地装好 Node、MySQL、Redis。这就像你在一艘船上到处堆满货物,换个船(服务器)就得重新搬一次。
  • Docker 容器化:Docker 就像海运的万吨巨轮,而每个容器就是一个标准集装箱。

核心公式:
Docker = 你的应用程序 + 它所需要的运行环境(Node版本、系统库等)

Docker 解决了什么问题?
解决了“在我的电脑上能跑,怎么在你电脑上就跑不起来了? ”这个世纪难题。

一个真实场景:
你到公司接手一个 n 年前的 Vue2 项目,要求 Node16 + npm8。你的电脑装的是 Node22,跑不起来。用 Docker 容器化虚拟技术,将各个依赖隔离安装,就能完美兼容。


二、Docker 核心概念:光盘(Image)与 DVD(Container)

刚开始接触 Docker,最容易搞混的就是 Image 和 Container。

概念比喻特点
镜像 (Image)光盘只读的。包含了应用程序和运行环境的蓝图。你可以把它 push 到远程仓库(比如 Docker Hub)。
容器 (Container)DVD可运行的。是镜像的一个实例。就像把光盘放进光驱播放,容器就是把镜像加载到内存里跑起来。

简单来说,我们通过 docker pull 拉取镜像(光盘),通过 docker run 运行镜像,生成容器(DVD)。


三、实战一:Node.js + Nginx 反向代理

我们先做一个最经典的组合:用 Docker 启动一个 Nginx,反向代理到本地的 Node.js 服务。

1. 准备 Node.js 服务(模拟后端)

写一个最简单的 Node.js HTTP 服务,监听 1314 端口。

文件名:index.js

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

# 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

# 命令分解:
# 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

用户浏览器访问 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!"
    ↓ (原路返回)
浏览器展示页面

四、实战二:MySQL 容器化部署(版本隔离)

前端开发中,数据库也是常见依赖。你的本地可能装了 MySQL 5.7,但项目需要 MySQL 8.0——版本不兼容,SQL 语法可能报错。用 Docker 拉取指定版本的镜像,就能和团队完全一致。

1. 拉取 MySQL 8.0 镜像

bash

# 拉取 MySQL 8.0 镜像(明确指定 tag,避免拉到 latest 版本)
docker pull mysql:8.0

2. 启动 MySQL 容器

bash

docker run -d \
  --name mysql-demo \              # 容器名字
  -p 3307:3306 \                   # 宿主机 3307 映射到容器 3306(避免和本地已有 MySQL 冲突)
  -e MYSQL_ROOT_PASSWORD=123456 \  # 设置 root 密码(生产环境请用强密码)
  mysql:8.0

参数解读:

  • -d:后台运行。
  • -p 3307:3306:把宿主机的 3307 端口映射到容器的 3306。这样你就可以用 localhost:3307 连接容器里的 MySQL,不会和你本机已有的 MySQL(通常占 3306)冲突。
  • -e:设置环境变量。MYSQL_ROOT_PASSWORD 是 MySQL 镜像约定好的变量,用来指定 root 密码。

3. 进入容器并操作数据库

bash

# 进入容器的 bash 终端(/bin/bash 是 Linux 的 shell)
docker exec -it mysql-demo /bin/bash

# 在容器内连接 MySQL
mysql -uroot -p123456

# 创建一个测试数据库
create database blog;

退出容器可以用 exit 命令(先退出 MySQL,再退出 bash)。之后你就可以在宿主机上用任何 MySQL 客户端(如 Navicat、DBeaver、VS Code 插件)连接 localhost:3307,用 root / 123456 登录,看到刚才创建的 blog 数据库。


五、组合起来:你的全套本地开发环境

现在你有了:

服务运行方式访问地址
Node.js 服务宿主机直接运行(node index.js)http://localhost:1314
Nginx 容器Docker 运行,反向代理到 Nodehttp://localhost:80
MySQL 容器Docker 运行,数据库服务localhost:3307(root/123456)

三者完全隔离,互不干扰,版本完全可控。以后换新电脑,只需把 Docker 命令复制一遍,环境秒级重建,不用再折腾各种版本安装包。


六、常用 Docker 运维指令(建议收藏)

开发过程中经常需要清理环境,这里整理了几个高频命令:

bash

# 1. 查看当前正在运行的容器
docker ps

# 2. 查看所有容器(包括已停止的)
docker ps -a

# 3. 停止所有正在运行的容器
docker stop $(docker ps -q)

# 4. 删除所有已停止的容器(释放磁盘空间)
docker rm $(docker ps -aq)

# 5. 删除指定的镜像(比如删除 nginx 镜像)
docker rmi nginx

# 6. 拉取任意想要的镜像(以 Redis 为例)
docker pull redis:7.0

# 7. 进入正在运行的容器内部(调试用)
docker exec -it 容器名字 /bin/bash

七、总结

通过这次实践,我们不仅了解了 Docker 的基本概念(镜像 vs 容器),还亲手搭建了一套包含 Node.js + Nginx 反向代理 + MySQL 数据库 的完整本地开发环境。

核心要点回顾:

  1. Docker 容器 = 应用 + 运行环境,解决了环境不一致的问题。
  2. 镜像(Image)  是静态的“光盘”,容器(Container)  是动态运行的“DVD”。
  3. 端口映射(-p)  是连接宿主机和容器的网络桥梁。
  4. 数据卷挂载(-v)  让修改配置文件变得像修改本地文件一样简单。
  5. 环境变量(-e)  可以快速配置容器内应用的运行时参数。
  6. docker exec -it 让你能进入容器内部,像操作 Linux 服务器一样调试。

希望这篇文章能帮你迈过 Docker 入门的门槛。如果你在实践过程中遇到问题,欢迎在评论区交流讨论! 😊