Docker 入门:从「光盘与 DVD」到全栈项目容器化实战

适合有 JavaScript / Node.js 开发经验、但零容器经验的工程师。

📌 导语

你接手了一个三年前的 Vue2 老项目,文档写着需要 Node 16 + npm 8,而你电脑装的是 Node 22 ------ 跑不起来。这几乎是每个开发者都会遇到的困境:「我的电脑能跑,你的电脑怎么跑?」。这篇文章就带你一次看懂 Docker 怎么解决这个问题。


一、💡 核心概念速览

Docker 是一个应用容器化工具,解决的核心问题就是上面那句「我的电脑能跑,你的电脑怎么跑」。

这句话背后有两组精妙的等式:

text 复制代码
Agent  = LLM + Harness(tool + mcp + rag + skill ...)
Docker = 应用 + 运行环境

你的代码从来不是孤立的------它依赖 Node、Redis、Next、React、MySQL 等一堆有版本要求的运行环境 。Docker 做的就是把这些依赖和代码打包成一个整体的容器,从而方便地部署到任何设备上。

经典类比 :镜像(Image)相当于「光盘」,是「应用程序 + 环境」的隔离封装;容器(Container)相当于「DVD」,是光盘被「运行」起来的实例。获取镜像就像 git pull 一样简单。


二、🔧 关键命令与操作清单

1. 运行容器:docker run

以一个「启动 nginx 镜像」的例子来演示 docker run,逐字拆解每个参数:

bash 复制代码
docker run \
  --name my-nginx-demo \
  -p 80:80 \
  -v D:\workspace\nginx.conf:/etc/nginx/nginx.conf \
  -d nginx
参数 含义
--name my-nginx-demo 给容器起名字
-p 80:80 本机80端口 : 容器80端口,做端口映射(80 是 nginx 监听端口)
-v 本机路径:容器路径 把本机配置文件挂载进容器
-d nginx 后台运行 nginx 镜像

因为 nginx 配置里 listen 80,而用户浏览器访问的是 http://localhost:80,所以 需要用 -p 把「本机 80」转发映射到「容器 80」。

2. 构建与分发镜像

bash 复制代码
docker build -t my-hello .   # 用 Dockerfile 构建镜像,-t 指定名字
docker login                 # 登录镜像仓库(如 GitHub)
docker push my-hello         # 推送镜像
docker pull my-hello         # 拉取镜像

3. 运维常用命令

bash 复制代码
docker pull mysql:8.0        # 拉取任意想要的镜像
docker stop $(docker ps -q)  # 停止所有运行中的容器
docker rm $(docker ps -aq)   # 删除所有容器
docker rmi nginx             # 删除 nginx 镜像

三、📦 Dockerfile:容器化的「标准操作手册」

Dockerfile 可以类比成蜜雪冰城的标准操作手册(SOP):写清「先加 xx、再加 xx、再加 xx」,任何人照着做,出来的味道都一样,于是就成了连锁店。

它本质上是一个文本配方文件,里面写着一行行做菜的指令,Docker 照着做就能自动「做」出一个一模一样的镜像:

dockerfile 复制代码
# 1. 选一个基础镜像
FROM node
# 2. 在容器里切到 /app 文件夹,设置工作目录
WORKDIR /app
# 3. 把本地代码复制进容器
COPY index.js .
# 4. 启动命令
CMD ["node", "index.js"]

配合一句 console.log('hello,Docker! 我跑到容器里了'),一个可运行的最小镜像就诞生了。

Dockerfile 是发布项目的标准方式之一。


四、🌐 Nginx 反向代理:一条真实数据流

从「运维」视角看一次用户请求的完整走向(正向代理 + 反向代理):

text 复制代码
用户上网 intent
  -> browser(Chrome)【正向代理】
  -> localhost:80
  -> docker -p(端口映射)
  -> container:80
  -> -v 映射的配置文件(本机 -> /etc/nginx/nginx.conf)
  -> nginx:80(配置中代理了 1314 端口)
  <- 1314(反向代理,Node 服务实际监听端口)

对应的配置与 Node 服务:

nginx 复制代码
# nginx.conf
events {}
http {
  server {
    listen 80;
    location / {
      proxy_pass http://host.docker.internal:1314;
      proxy_set_header Host $host;
    }
  }
}
js 复制代码
// 早期 commonjs 规范,Node 服务监听 1314 端口
server.listen(1314, '0.0.0.0', () => {
  console.log('node service run on 1314');
});

因为 nginx 监听 80 端口的高并发访问、并把请求转发给 1314,所以 用户(localhost)根本不知道后端实际跑在哪个端口------这就是反向代理的意义。nginx 常用于「高并发、代理转发」场景。


五、⚠️ 常见误区与避坑指南

  1. 混淆「镜像」与「容器」 :镜像(Image)是「光盘」------静止、隔离的封装;容器(Container)是「DVD」------光盘被运行起来的实例。构建得到的是镜像,docker run 出来才是容器。

  2. 端口映射方向写反 :-p 80:80 是「本机:容器」,不是「容器:本机」。本机端口必须写在冒号左边。

  3. host.docker.internal 不能少 :容器内访问宿主机服务要用这个地址,不能写 localhost------因为容器里的 localhost 指向容器自己。

  4. 别忽略「运行环境」的版本问题:Node 项目依赖特定 Node/npm 版本,换了环境就「跑不起来」。容器的价值在于把「有版本要求的运行环境」一并打包,而不仅是打包代码。

  5. 跨域本质是「同源策略」 :全栈项目中 5173:3000 之所以跨域,是因为同源策略把前后端不同端口视为「不同源」。解决思路有三类:CORS 服务器端配置响应头 、Vite 代理配置 、axios baseURL:'/api' 配合 Nginx 反向代理。


六、🎯 实战场景映射

场景一:全栈项目容器化与跨域

一个「前端 React + TS + zustand + axios,后端 Nest.js + Todo Module」的全栈项目,核心考点落在跨域:

text 复制代码
后端接口统一为 /api/todos
前端 axios 封装时把 baseURL 设为 '/api',配合 Nginx 反向代理统一转发
规避「5173:3000」的同源限制

跨域(CORS,Cross-Origin Resource Sharing,跨域资源共享)的解决方式:CORS 服务器端配置响应头 、或 Vite 代理配置。

这一步把「nginx 反向代理」和「全栈跨域」两个知识点,落地到日常开发最头疼的「前后端联调」场景。

场景二:多镜像编排(Milvus)

当一个服务需要多个镜像时,用 docker-compose 文件来编排多个 image 的工作流。

一个 Milvus 的 docker-compose.yml 可以一口气编排三个服务:

  • etcd(元数据存储)、minio(对象存储)、standalone(Milvus 主服务)
  • 通过 depends_on 声明启动顺序(standalone 依赖 etcd 与 minio)
  • 通过 healthcheck 做健康检查、ports 映射端口、volumes 挂载持久化目录
yaml 复制代码
services:
  etcd:
    image: quay.io/coreos/etcd:v3.5.25
    # ... 省略配置
  minio:
    image: minio/minio
    # ... 省略配置
  standalone:
    image: milvusdb/milvus:v3.0.0
    command: ["milvus", "run", "standalone"]
    depends_on:
      - etcd
      - minio

对应的业务代码是「Milvus 向量库 + OpenAI Embeddings」的 AI 应用,用 MilvusClient 建集合、建索引、插入向量数据------这是「容器编排」和「AI 向量检索」结合的典型落地。


七、小结

一套清晰的学习主线:

text 复制代码
为什么(版本不一致跑不起来) -> 是什么(镜像=光盘,容器=DVD)
  -> 怎么做(run 跑容器 -> Dockerfile 建镜像 -> push/pull 分发)
  -> 进阶(nginx 反代 -> compose 编排 -> 全栈与 AI 落地)

掌握这六步,你就已经能把手头的 Node 项目、全栈项目、甚至 AI 向量库服务都「装进集装箱」,在任何一台机器上原样跑起来了。

相关推荐
晚安日记wanna43 分钟前
订单30分钟未支付自动取消:定时任务为什么被面试官嫌弃
redis·后端·面试
橘和柠1 小时前
阿里 open-code-review (AI代码审查工具)实战:安装、四层规则链、自定义规则格式与实测避坑
算法·面试
探索云原生1 小时前
一个 Deployment 就能跑 vLLM,为什么还需要 KServe?
docker·ai·云原生·kubernetes·go
Solis1 小时前
MVCC原理
后端·面试
mCell1 小时前
程序员即将隐退,建造者持续闪耀
面试·agent·求职
广白1 小时前
Git Tag 实战:从出包追溯到版本发布
前端·git·面试
怕浪猫1 小时前
AI 知识库 WeKnora(腾讯微信团队出品)
后端·面试·github
虎头金猫5 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
分布式存储与RustFS5 天前
MinIO 官方 Docker 镜像被移除:依赖它的项目该怎么办
docker·云原生·devops·对象存储·minio·分布式存储