如何在Flutter应用中通过Dio解析容器IP解决API调用失败问题
问题根源
浏览器运行在宿主机网络环境,而非Docker容器的内部网络,所以无法识别docker-compose中定义的backend服务名——只有Docker内部网络里的容器才能通过服务名互相访问,这就是为什么你在Flutter容器里用curl能通,但浏览器调用报错的原因。
解决方案
方案1:直接使用宿主机IP/localhost(本地开发首选)
把代码里的API地址替换成宿主机的IP或者localhost(本地开发时用),因为你已经在docker-compose里把后端的8888端口映射到了宿主机:
void fetchData() async { try { setState(() { isLoading = true; }); // 替换为localhost或你的宿主机实际IP var response = await dio.get( "http://localhost:8888/api/screen", ); if (response.statusCode == 200) { setState(() { lineData = jsonDecode(response.data); isLoading = false; }); } } on DioError catch (err) { print(err); isLoading = false; } catch (_) { setState(() { isLoading = false; }); } }
方案2:配置反向代理(生产环境推荐)
用Nginx做反向代理,把前端和后端的请求统一由Nginx转发,前端请求用相对路径,避免硬编码IP。修改docker-compose.yml新增Nginx服务:
version: '3' services: playground-web-frontend: build: context: ./flutterapp dockerfile: frontend.dockerfile # 不再直接映射端口,由Nginx转发 backend: image: backend nginx: image: nginx:alpine volumes: - ./nginx.conf:/etc/nginx/nginx.conf ports: - 4040:80
然后创建nginx.conf配置文件:
events {} http { server { listen 80; # 前端请求转发 location / { proxy_pass http://playground-web-frontend:4040; } # API请求转发到后端 location /api/ { proxy_pass http://backend:8888/api/; } } }
最后修改Flutter代码里的API地址为相对路径:
var response = await dio.get("/api/screen");
方案3:修改宿主机hosts文件(仅本地临时测试用)
在宿主机的hosts文件中添加一行:
127.0.0.1 backend
这样浏览器会把backend解析到本地,但这个方法只适合本地开发测试,线上环境不适用。
内容的提问来源于stack exchange,提问作者saturn
相关产品推荐
相关产品推荐

