Azure Ubuntu 20.04 LTS虚拟机中配置Nginx为Docker容器提供SSL服务并实现Flutter容器本地调用Node.js API
嘿,看你的描述,你已经在Azure上的Ubuntu 20.04 LTS虚拟机里跑了两个Docker容器——一个Flutter Web应用,一个Node.js API服务,还搞定了Certbot的SSL证书,现在核心需求是让Flutter容器不用绕外部域名https://nodejs.example.com/example/endpoint,直接在本地(容器内部网络)调用Node.js API,同时还要保证两个域名能对外提供服务对吧?刚好可以用Nginx反向代理同时解决这两个问题,我给你一步步捋清楚怎么做:
一、先搞定Flutter容器内部本地调用Node.js API
因为两个容器都在默认的bridge Docker网络里,其实不用走外部域名,直接利用Docker内部网络就能访问,而且这样速度更快、更稳定:
- 如果你启动Node.js容器的时候指定了容器名(比如
docker run --name nodejs-api ...),那在Flutter容器里直接用http://nodejs-api:5000/example/endpoint就能调用API了,容器名在同一网络里是可以直接解析的,比用内部IP靠谱,毕竟容器重启后IP可能会变。 - 要是之前没指定容器名,先给Node.js容器重命名:
docker rename <你的Node.js容器ID> nodejs-api,之后Flutter容器里就能用这个名字访问了。
这里要注意:容器内部的调用不用走HTTPS,因为你把SSL证书装在了主机上,内部网络直接用HTTP访问容器端口就行。
二、配置Nginx反向代理处理外部SSL访问
接下来要让外部用户能通过flutter.example.com和nodejs.example.com安全访问你的服务,同时利用你已经用Certbot生成的SSL证书,步骤如下:
安装Nginx
先确保主机上装了Nginx,没装的话执行:sudo apt update sudo apt install nginx -y创建Nginx站点配置文件
分别给Flutter Web和Node.js API创建配置文件,分开管理更清晰:创建Flutter站点配置:
sudo nano /etc/nginx/sites-available/flutter.example.com
粘贴以下内容(记得替换SSL证书路径为你实际的路径):server { listen 80; server_name flutter.example.com; # 把所有HTTP请求重定向到HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl; server_name flutter.example.com; # Certbot生成的SSL证书路径 ssl_certificate /etc/letsencrypt/live/flutter.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/flutter.example.com/privkey.pem; location / { # 反向代理到Flutter容器的内部IP和端口 proxy_pass http://172.17.0.4:5556; # 传递必要的请求头,避免服务端获取不到正确的请求信息 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }创建Node.js API站点配置:
sudo nano /etc/nginx/sites-available/nodejs.example.com
粘贴以下内容(同样替换SSL证书路径):server { listen 80; server_name nodejs.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name nodejs.example.com; ssl_certificate /etc/letsencrypt/live/nodejs.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/nodejs.example.com/privkey.pem; location / { proxy_pass http://172.17.0.2:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 如果你的API有跨域需求,加上这些CORS配置 add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; } }
启用配置并重启Nginx
- 把配置文件软链接到Nginx的启用站点目录:
sudo ln -s /etc/nginx/sites-available/flutter.example.com /etc/nginx/sites-enabled/ sudo ln -s /etc/nginx/sites-available/nodejs.example.com /etc/nginx/sites-enabled/ - 检查配置是否有语法错误:
sudo nginx -t - 如果提示
test is successful,就重启Nginx生效:sudo systemctl restart nginx
- 把配置文件软链接到Nginx的启用站点目录:
配置Azure防火墙规则
别忘了在Azure虚拟机的网络安全组里打开80(HTTP)和443(HTTPS)端口,不然外部用户访问不了你的服务。
三、额外优化:用Docker Compose管理容器(可选)
如果以后容器数量增多,用Docker Compose来管理会更省心,还能自定义专属网络,让容器之间的访问更稳定。比如创建一个docker-compose.yml文件:
version: '3.8' services: flutter-web: image: 你的Flutter容器镜像名称 container_name: flutter-web networks: - app-network ports: - "5556:5556" # 主机端口:容器端口,可根据实际调整 nodejs-api: image: 你的Node.js容器镜像名称 container_name: nodejs-api networks: - app-network ports: - "5000:5000" networks: app-network: driver: bridge
启动后,Flutter容器里直接用http://nodejs-api:5000/example/endpoint就能调用API,不管容器怎么重启,名字都不会变,比依赖内部IP稳定多了。
备注:内容来源于stack exchange,提问作者Abdelrahman Ayman

