🧐 为什么需要 Docker?(那个著名的“甩锅”现场)
在 Docker 出现之前,开发和运维之间经常发生这样的争吵:
- 开发 (Dev):“代码我写好了,在我电脑上跑得好好的!” 😤
- 运维 (Ops):“放屁!部署到服务器上直接报错,缺这个库缺那个包,跑不起来!” 😡
这就是环境一致性问题。
你的电脑是 Mac,服务器是 Linux;你装了 Node 18,服务器只有 Node 14。
每次部署,运维都要手动安装一堆环境,极其容易出错。
💡 救星来了:集装箱 (Container)
Docker 的灵感来自于海运集装箱。
- 以前 (散货):码头工人要搬运钢琴、香蕉、汽车。有的怕压,有的怕水,很难堆叠,搬运效率极低。
- 现在 (集装箱):不管货物是什么,统统装进一个标准尺寸的铁盒子里。
- 吊车不需要知道盒子里装的是什么,只管吊盒子。
- 轮船不需要专门改造,只管堆盒子。
Docker 就是软件行业的集装箱。
它把你的代码、依赖库、操作系统环境、配置文件,统统打包进一个“盒子”里。
无论在这个盒子里装了什么乱七八糟的东西,到了服务器上,只需要把盒子跑起来就行!
🏗️ 核心概念:Docker 三剑客
Docker 的世界里有三个最重要的概念,一定要分清:
1. 镜像 (Image) = “安装光盘” 💿
- 只读的。
- 它就像是一个打包好的
Windows.iso安装文件,或者游戏的安装包。 - 里包含了代码运行所需的一切(代码 + Node.js + Linux 系统精简版)。
- 比喻:它是冻结的,不会变的。
2. 容器 (Container) = “运行中的程序” 🏃♂️
- 可读写的。
- 当你运行镜像时,就产生了一个容器。
- 你可以基于一个镜像,启动 10 个相同的容器(就像用一张光盘安装了 10 台电脑)。
- 比喻:它是活的,可以随时创建、随时销毁。
3. 仓库 (Repository) = “应用商店” 🏪
- 存放镜像的地方。
- 最著名的是Docker Hub。
- 你可以从上面下载别人写好的镜像(如 Nginx, Redis, MySQL),也可以把自己写的镜像传上去。
⚔️ Docker vs 虚拟机 (VM)
很多人问:“这不就是虚拟机吗?”
大错特错!
| 特性 | 虚拟机 (VM) | Docker 容器 |
|---|---|---|
| 原理 | 盖一栋楼🏠 | 隔一个胶囊房💊 |
| 重量 | 巨重 (几 GB) | 超轻 (几 MB - 几百 MB) |
| 启动速度 | 慢 (几分钟) | 秒级⚡️ |
| 资源消耗 | 独占 CPU/内存,浪费严重 | 共享宿主机内核,按需使用 |
| 包含内容 | 完整的 Guest OS (Windows/Linux) | 只有代码和必要的库 |
总结:Docker 比虚拟机轻量得多,因为它不需要模拟硬件,也不需要完整的操作系统,它只是在宿主机上隔离出了一块小空间。
📝 实战:把 Vue 项目装进 Docker
假设你写好了一个 Vue 项目,怎么用 Docker 部署?
我们需要写一个说明书:Dockerfile。
1. 编写 Dockerfile
这是一个文本文件,告诉 Docker 怎么打包你的项目。
# 第一阶段:构建 (Build) # 找一个装了 Node.js 的环境作为基础 FROM node:18 as build-stage # 设置工作目录 WORKDIR /app # 把 package.json 复制进去 COPY package.json ./ # 安装依赖 (npm install) RUN npm install # 把所有代码复制进去 COPY . . # 开始打包 (npm run build) RUN npm run build # -------------------------------------------------- # 第二阶段:运行 (Run) # 找一个 Nginx 环境作为基础 (因为 Vue 打包后是静态文件) FROM nginx:stable-alpine as production-stage # 把刚才第一阶段打包好的 dist 文件夹,复制到 Nginx 的目录里 COPY --from=build-stage /app/dist /usr/share/nginx/html # 暴露 80 端口 EXPOSE 80 # 启动 Nginx CMD ["nginx", "-g", "daemon off;"]2. 制作镜像 (Build Image)
在终端执行:
# 把当前目录打包成一个叫 my-vue-app 的镜像dockerbuild-tmy-vue-app.3. 运行容器 (Run Container)
# 在后台运行 (-d)# 把宿主机的 8080 端口映射到容器的 80 端口 (-p 8080:80)dockerrun-d-p8080:80 my-vue-app现在,访问http://localhost:8080,你的 Vue 项目就跑起来了!
无论你把这个镜像发给谁,只要他装了 Docker,运行结果绝对和你一模一样。
📊 图解:Docker 工作流
🚀 进阶知识:不仅仅是“跑起来”
1. 💾 数据去哪了?(数据卷 Volume)
你可能会问:“如果我把 MySQL 容器删了,我的数据还在吗?”
答案是:不在了!😱 容器就像一个临时酒店房间,退房(删除容器)后,里面的东西都会被清空。
为了保存数据(比如数据库文件、用户上传的图片),我们需要数据卷 (Volume)。
它的原理很简单:把宿主机(你的电脑)的一个文件夹,挂载到容器里。
# -v 宿主机路径:容器路径dockerrun-d-v/my/data:/var/lib/mysql mysql这样,即使容器炸了,数据还在你的电脑硬盘里。
2. 🎻 如果不止一个容器?(Docker Compose)
真实项目通常包含:前端(Vue) + 后端(Node) + 数据库(MySQL)。
如果每次都要手动敲 3 个docker run命令,还要配置它们怎么互相通信,太累了。
Docker Compose就是一个乐团指挥家。
你只需要写一个docker-compose.yml文件:
version:'3'services:web:image:my-vue-appports:-"8080:80"api:image:my-node-apidb:image:mysqlvolumes:-./data:/var/lib/mysql然后敲一行命令:
docker-composeup-d三个容器就全部整整齐齐地跑起来了!
🕹️ 常用命令速查
| 命令 | 作用 |
|---|---|
docker ps | 查看正在跑的容器 |
docker ps -a | 查看所有容器(包括挂掉的) |
docker stop <id> | 停止容器 |
docker rm <id> | 删除容器 (必须先停止) |
docker rmi <id> | 删除镜像 |
docker logs <id> | 查看容器日志 (报错时必看!) |
docker exec -it <id> sh | 进入容器内部 (像 SSH 一样) |
🧠 总结
- Docker解决了“环境不一致”的千古难题。
- 它像集装箱一样,把代码和环境打包在一起。
- 它比虚拟机更轻、更具、更省资源。
- 它是现代DevOps和微服务的基石。