上一篇介绍了 Docker 的核心思想:
Docker = 应用 + 运行环境
它解决的是:
"我的电脑能运行,你的电脑为什么不能运行?"
实际开发中,一个项目通常依赖很多环境:
vbnet
Node
Redis
MySQL
React
Next
Nginx
这些服务都有自己的版本要求。
Docker 可以将它们分别封装成独立的运行环境。
例如:
项目
├── Node Container
│
├── Redis Container
│
├── MySQL Container
│
└── Nginx Container
每个服务独立运行,又可以互相通信。
本文通过一个简单 Web 服务,理解 Docker 如何运行 Nginx,并通过 Nginx 代理后端 Node 服务。
1. 一个简单 Web 服务
假设现在有一个 Node 后端服务。
代码:
javascript
const express = require("express")
const app = express()
app.get("/", (req, res) => {
res.send("Hello Docker")
})
app.listen(1314, () => {
console.log("server running at 1314")
})
启动:
node app.js
服务运行:
makefile
localhost:1314
访问:
arduino
http://localhost:1314
浏览器可以得到:
Hello Docker
目前请求流程:
浏览器
↓
Node服务
↓
返回数据
2. 为什么需要 Nginx?
如果只是本地开发:
makefile
浏览器
↓
localhost:1314
↓
Node
完全没有问题。
但是生产环境中,用户通常不会直接访问:
makefile
xxx.com:1314
原因:
- 用户不应该知道后端端口
- 不同服务可能运行在不同端口
- 需要统一入口管理请求
例如:
用户访问:
www.example.com
默认访问:
80端口
但是我们的 Node 服务:
yaml
1314端口
所以需要一个中间层:
用户
↓
Nginx :80
↓
Node :1314
这个过程叫:
反向代理(Reverse Proxy)
3. Nginx 做什么?
Nginx 是一个服务器软件。
在这里,它主要负责:
- 监听用户请求
- 根据配置转发请求
- 隐藏后端真实服务地址
例如:
用户访问:
makefile
localhost:80
Nginx 根据配置:
arduino
location / {
proxy_pass http://localhost:1314;
}
转发:
makefile
localhost:80
↓
localhost:1314
用户只知道:
makefile
localhost:80
不知道:
Node运行在1314端口
4. 使用 Docker 运行 Nginx
Docker 最大的特点:
不需要手动安装环境。
我们直接使用 Nginx 官方镜像。
拉取镜像:
docker pull nginx
得到:
nginx Image
Image 可以理解为:
一个已经准备好的运行环境模板。
运行:
arduino
docker run nginx
Docker 会根据 Image 创建:
nginx Container
Container 才是真正运行的 Nginx 服务。
5. docker run 参数解析
实际运行:
diff
docker run \
--name my-nginx-demo \
-p 80:80 \
-v /Users/shunwuyu/Desktop/ai_doubao_ysw/backend/docker/demo/nginx.conf:/etc/nginx/nginx.conf \
-d nginx
这个命令包含几个重要概念。
5.1 --name:给 Container 命名
css
--name my-nginx-demo
给创建出来的容器命名:
makefile
Container
name:
my-nginx-demo
之后可以通过名字管理:
arduino
docker stop my-nginx-demo
5.2 -p:端口映射
css
-p 80:80
格式:
本机端口 : Container端口
这里表示:
电脑80端口
映射
Nginx Container的80端口
因此:
浏览器访问:
makefile
localhost:80
请求进入:
Nginx Container:80
流程:
浏览器
↓
电脑80端口
↓
Docker端口映射
↓
Container 80端口
5.3 -v:挂载配置文件
ruby
-v 本机文件:/container文件
例如:
javascript
-v nginx.conf:/etc/nginx/nginx.conf
作用:
把电脑上的:
nginx.conf
映射到:
bash
Container内部:
/etc/nginx/nginx.conf
为什么需要?
因为 Nginx 的转发规则需要配置。
我们修改本机:
nginx.conf
Container 中的 Nginx 就会读取新的配置。
5.4 -d:后台运行
diff
-d
表示:
detach
让 Container 在后台运行。
否则:
arduino
docker run nginx
终端会一直显示 Nginx 日志。
6. nginx.conf 配置反向代理
例如:
markdown
server {
listen 80;
location / {
proxy_pass http://host.docker.internal:1314;
}
}
含义:
监听:
80端口
如果收到请求:
转发给:
yaml
1314端口的Node服务
7. 完整请求流程
现在整个系统:
markdown
浏览器
|
↓
localhost:80
|
↓
Docker端口映射(-p)
|
↓
Nginx Container
|
↓
nginx.conf配置
|
↓
proxy_pass
|
↓
Node服务:1314
|
↓
返回数据
具体过程:
第一步
用户访问:
makefile
localhost:80
第二步
请求进入 Docker:
css
-p 80:80
将电脑80端口映射到:
Nginx Container:80
第三步
Nginx 接收到请求。
读取:
nginx.conf
发现:
arduino
proxy_pass http://host.docker.internal:1314;
第四步
Nginx 将请求转发:
makefile
Node服务:1314
第五步
Node 返回结果:
Node
↓
Nginx
↓
浏览器
8. Docker 在这个流程中的作用
这里有两个角色:
Nginx Container
负责:
接收请求
↓
转发请求
Node 服务
负责:
业务逻辑
↓
返回数据
最终结构:
markdown
Docker
├── Nginx Container
│ ↓
│ 反向代理
│
└── Node服务
↓
处理业务
9. 运维常用 Docker 命令
查看运行中的 Container:
docker ps
停止所有 Container:
arduino
docker stop $(docker ps -q)
删除所有 Container:
bash
docker rm $(docker ps -aq)
删除镜像:
docker rmi nginx
拉取 MySQL:
docker pull mysql:8.0
总结
Docker 解决:
应用运行环境一致的问题。
Nginx 解决:
请求入口和服务转发的问题。
在这个例子中:
makefile
用户
↓
localhost:80
↓
Nginx Container
↓
Node服务:1314
Docker 负责运行 Nginx 和 Node。
Nginx 负责把用户请求转发给真正处理业务的服务。
这就是一个最基础的 Docker Web 部署流程。