面试官的灵魂拷问
去公司报到第一天,老板甩给你一个五年前的老项目:vue2 + Node 16。你兴冲冲打开电脑------自己装的是 Node 22,npm install 报错、编译失败、页面白屏。你重装 Node 16?那你手上自己的新项目又跑不起来了。
这个场景几乎每个程序员都遇到过。问题本质在于:代码只是软件的一半,它背后还依赖一堆有版本要求的运行环境(Node、MySQL、Redis、Nginx......)。环境一不对,同样的代码就废了。
Docker 就是为解决这个世纪难题而生的。
Docker 是什么?先理解"集装箱"思维
想象海运。没有集装箱之前,货物五花八门,装船卸船极其麻烦。集装箱出现后,不管里面装的是苹果还是汽车,尺寸统一、吊机一吊就走,运输效率起飞。
Docker 就是软件世界的集装箱。它把应用 + 运行环境 打包成一个整体:里面的 Node 16 就是 Node 16,MySQL 8 就是 MySQL 8,和外界完全隔离。只要机器上装了 Docker,这个"箱子"就能原样跑起来。用公式记:Docker = 应用 + 运行环境。
两个核心概念:镜像(Image)和容器(Container)
- 镜像(Image) :可以理解成一张"光盘",里面刻录好了应用和环境,是只读的模板 。它从哪来?
docker pull nginx从云端仓库"拉"下来,类似git pull。 - 容器(Container) :可以理解成"DVD 播放机"。把光盘放进去,它就开始转了。
docker run就是"把镜像启动成一个正在运行的容器"。
一句话:镜像是不可变的模板,容器才是正在运行的实例。想改代码?重新构建镜像,而不是去改正在跑的容器。
端口映射:容器和外面怎么通信?
容器是封闭的,外界怎么访问里面的服务?靠端口映射。看这条命令:
bash
docker run --name my-nginx-demo -p 80:80 -d nginx
拆开看:
--name:给容器起个名字,方便管理-p 80:80:第一个 80 是本机端口,第二个 80 是容器内端口。含义是"访问本机的 80 端口,自动转发给容器里的 80 端口"-d:后台运行,不一直占着终端
于是浏览器访问 localhost:80,流量就被 Docker 送进容器,交给里面的 Nginx。
真实场景:Node 服务 + Nginx 反向代理
我们写了两个组件:
- 一个 Node 小服务 (
demo/index.js),用http模块在 1314 端口返回一句 "hello world" - Nginx 服务器 ,默认监听 80 端口
问题来了:用户只输入 localhost(走的 80 端口),怎么访问到 1314 端口的 Node 服务?答案就是 Nginx 反向代理 。看 nginx.conf:
nginx
server {
listen 80;
location / {
proxy_pass http://host.docker.internal:1314;
}
}
listen 80:Nginx 在容器内的 80 端口接收请求proxy_pass:收到请求后,悄悄转发给1314端口,再把响应带回来host.docker.internal:这是 Docker 给"宿主机"起的固定名字。容器是隔离的,不知道宿主机在哪,用这个名字才能找到真正运行 Node 的那台机器
于是整条链路是:
rust
浏览器 -> 本机 80 端口 -> (Docker -p 80:80) -> 容器内 Nginx 80 -> (proxy_pass) -> Node 1314
什么是反向代理?为什么是运维考点?
作为用户,你只知道自己访问了 80 端口,根本不知道背后真正的服务跑在哪个端口 。把请求接收下来、再转交给真正干活的服务器,这就是反向代理。它有三大好处:
- 隐藏真实服务:内部端口和服务器结构对用户不可见,更安全
- 负载均衡:请求多了,可以转发给多台后端,分摊压力
- 统一入口:所有服务都从 80 端口进,Nginx 按路径分发给不同服务
卷挂载:把配置文件"装"进容器
容器重启后文件就丢了,配置改起来很麻烦。-v 卷挂载可以把本机文件"映射"进容器:
bash
-v /root/xy_ai/docker/demo/nginx.conf:/etc/nginx/nginx.conf
意思是:本机的 nginx.conf 和容器里的这份是同一个文件,改本机的,容器内立刻生效。这也是"本地改配置、容器里跑服务"的标准姿势。
常用命令速查
bash
docker pull nginx # 拉镜像
docker run -p 80:80 nginx # 跑容器
docker stop $(docker ps -q) # 停掉所有容器
docker rm $(docker ps -aq) # 删掉所有容器
docker rmi nginx # 删除镜像