Rust-虽然9天过去了,结果是没有结果(Docker容器的端口映射问题)

这篇文章收录于Rust 实战专栏。这个专栏中的相关代码来自于我开发的笔记系统。它启动于是2023年的9月14日。相关技术栈目前包括:Rust,Javascript。关注我,我会通过这个项目的开发给大家带来相关实战技术的分享。


前言

上上周了吧,写了一篇Rust-后端服务调试入坑记,现在看来那个坑根本就不算什么。这次这个坑才是真正的坑。到写文章这一刻,我只是确定了复现这个问题的最简单代码(参考目录验证4:基于Debian:11镜像创建最简单Rust的http服务)。但依然没有找到解决这个问题的办法。

现在把这个问题以及我的验证过程整理出来,以便路过的朋友了解,我相信肯定有大神知道其中的缘由和解决办法。还望各位大神留言赐教。

问题描述

我用Rust语言创建了一个基于Rocket框架(0.5-rc)的Restful服务api(以下简称api),并将其部署在docker容器内调试。
在这里插入图片描述

容器相关描述:

  • 容器名称: notes-api
  • 网络模式: bridge
  • 端口映射: 8003:8000

当容器成功启动后,问题及相关情况描述:

  • 不能从宿住机访问容器中的api,错误码56,命令行: curl http://localhost:8003/api/notes
  • 能够从宿主机上ping通容器,命令行:ping 172.22.0.2
  • 登录到容器中,能够运行命令行成功访问api,命令行: sudo docker exec -it notes-api curl http://localhost:8000/api/notes
  • 如果将网络模式改为host,能够从宿主机上正常访问容器中的api,命令行: curl http://localhost:8000/api/notes

对自己的怀疑

这个问题导致了我对我的Docker使用经验和相关的记忆产生怀疑。难道Docker容器在网络模式为bridge时,不能从宿住机访问?很快,这个问题被否定了,因为我早些时候就在Nginx服务器上配置过多个api的路由,这些api都通过Docker部署在一台服务器上,通过不同的端口来访问部署在这些容器中的api。
即然是早些时候,我的下一个判断是,会不会是因为我现在这台服务器上安装的Docker版本比较新,新版本的Docker Engine是否有一些关于端口映射的设置,导致部署在Docker容器中的api不能够被正常访问呢?

验证之路

1. Python应用

说实话,我的关于用Docker容器部署Api的经验主要来至于Python。我还是第一次将Rust构建的api部署到Docker容器中。因此,我决定用Python创建一个简单的api,将其部署到Docker容器中,看是否能够从宿主机上正常访问。
docker-compose.yml

version: '3'services:  web:build:context: ./dockerfile: Dockerfilecontainer_name: python-apinetwork_mode: bridgeports:- 8004:5000

Dockerfile

from python:latestworkdir /app
copy ./main.py ./requirements.txt /app/run pip install -r requirements.txt
cmd ["python3", "main.py"]

结果:能够从宿主机上成功访问到容器内的api。

因此,是不是镜像本身的问题呢?
我对比了Python镜像和Rust镜像所使用的linux系统。Python镜像使用的是"Debian GNU/Linux 11",Rust使用的是"Debian GNU/Linux 12"。

2. 从Debian:11镜像来创建Rust的镜像

因此,我决定基于Debian:11的镜像来制作Rust的api容器的镜像。
docker-compose.yml

version: '3'
services:  web:build:context: ./dockerfile: Dockerfilecontainer_name: notes-api1network_mode: bridgeports:- 8004:8000

Dockerfile

from debian:11
run apt update
run apt install -y curl gccrun curl -s --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y 
env PATH=/root/.cargo/bin:$PATH 
run rustup default nightlyworkdir /appcopy ./Cargo.toml ./config.toml ./Cargo.lock /app/
copy ./src /app/srccmd ["cargo", "run"]

结果:不能从宿主机访问Docker容器中的api。
会不会是Python的镜像虽然基于"Debian GNU/Linux 11",但是,在制作镜像的时候有一些设置关于端口映射的设置呢?

3. 从Debian:11镜像来创建Python的镜像

因此,为了排出关于“设置”的猜想,我决定基于Debian:11的镜像来制作Python的api容器的镜像。
如果能够正常访问,说明不存在关于“设置”的猜想。
docker-compose.yml

version: '3'services:  web:build:context: ./dockerfile: Dockerfilecontainer_name: my-python2 network_mode: bridgeports:- 8009:5000

Dockerfile

from debian:11
run apt update
run apt install -y curl gccrun apt install python3 pip -yworkdir /app
copy ./main.py ./requirements.txt /app/env PATH=/usr/local/bin:$PATHrun pip install -r requirements.txtcmd ["python3", "main.py"]

结果:能够从宿主机上成功访问到容器内的api。
说明,Python的镜像中,关于端口映射的相关“设置”猜想不存在。

因此,我的视线又回到了Rust项目,我的api是基于Rocket 0.5-rc开发的,是不是因为这个框架的原因呢?

4. 基于Debian:11镜像创建最简单Rust的http服务

因此,我让AI帮我写了一个没有任何依赖的Rust的http服务,然后将这个服务部署到基于Debian:11的镜像中。
docker-compose.yml

version: '3'
services:  web:build:context: ./dockerfile: Dockerfilecontainer_name: rust-simple-httpnetwork_mode: bridgeports:- 8012:8080

Dockerfile

from debian:11
run apt update
run apt install -y curl gcc# 安装rust
run curl -s --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y 
env PATH=/root/.cargo/bin:$PATH workdir /appcopy ./Cargo.toml ./entry.sh /app/
copy ./src/main.rs /app/src/main.rsentrypoint ["./entry.sh"]

main.rs

use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};fn handle_client(mut stream: TcpStream) {let mut buffer = [0; 1024];stream.read(&mut buffer).unwrap();let response = "HTTP/1.1 200 OK\r\n\r\nHello, World!";stream.write(response.as_bytes()).unwrap();stream.flush().unwrap();
}fn main() {let listener = TcpListener::bind("127.0.0.1:8080").unwrap();for stream in listener.incoming() {match stream {Ok(stream) => {std::thread::spawn(|| {handle_client(stream);});}Err(e) => {eprintln!("Failed to establish a connection: {}", e);}}}
}

entry.sh

#!/bin/bashecho "cargo build"
cargo build --release
echo "cp bin"
cp target/release/app ./
echo "run app"
./app

结果: 不能从宿主机访问Docker容器中的api。
因此,貌似和Rocket 0.5-rc这个框架没有关系。

目前的情况可以归纳为:

  1. Rust创建的api部署到容器中,容器的网络模式为bridge,不能够从宿主机通过容器的端口访问到容器中运行的api。
  2. Python创建的api部署到容器中,容器的网络模式为bridge,能够从宿主机通过容器的端口访问到容器中运行的api。

这个特殊现象是否只存在于Rust和Python之间呢?如果再找一个应用部署到网络模式为bridge的Docker容器中,能否从宿主机通过容器端口访问到容器中运行的应用呢?如果答案是“能”,那么,多少可以得出结论:

Rust创建的api部署到网络模式为bridge的Docker容器中,不能从宿主机通过容器的端口访问到容器中运行的api。

5. 基于Debian:11镜像从apt安装简单的http服务

docker-compose.yml

version: '3'
services:  web:build:context: ./dockerfile: Dockerfilecontainer_name: simple-http-servernetwork_mode: bridgeports:- 8013:8080

Dockerfile

from debian:11
run apt update
run apt install -y curl gccrun apt install libhttp-server-simple-perl -yworkdir /app
copy entry.sh /app/
entrypoint ["./entry.sh"]

entry.sh

#!/bin/bash
perl -MHTTP::Server::Simple -e 'my $server = HTTP::Server::Simple->new(); $server->run()'

结果:能够从宿主机上成功访问到容器内的api。

结论

看来目前只能得出这样的结论了:
Rust创建的api部署到网络模式为bridge的Docker容器中,不能从宿主机通过容器的端口访问到容器中运行的api。

问题整理好了,先放在这里。

后面的工作如何开展

暂时将容器的网络模式设置为host进行调试。如果后面配置的服务很多,估计需要做一个cli来管理各个服务端口的配置(这可是我的强项,哈哈)。

如有问题,欢迎大家留言交流。关注我,后面会在Rust 实战专栏中给大家带来更多关于Rust开发实战的分享。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/175818.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

机器学习(六)构建机器学习模型

1.9构建机器学习模型 我们使用机器学习预测模型的工作流程讲解机器学习系统整套处理过程。 整个过程包括了数据预处理、模型学习、模型验证及模型预测。其中数据预处理包含了对数据的基本处理,包括特征抽取及缩放、特征选择、特征降维和特征抽样;我们将…

Linux的简介和环境搭建

简介 Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和Unix的多用户、多任务、支持多线程和多CPU的操作系统。它能运行主要的Unix工具软件、应用程序和网络协议。它支持32位和64位硬件。Linux继承了Unix以网络为核心的设计思想,是一个…

Python构造代理IP池提高访问量

目录 前言 一、代理IP是什么 二、代理IP池是什么 三、如何构建代理 IP 池 1. 从网上获取代理 IP 地址 2. 对 IP 地址进行筛选 3. 使用筛选出来的 IP 地址进行数据的爬取 四、总结 前言 爬虫程序是批量获取互联网上的信息的重要工具,在访问目标网站时需要频…

#stm32整理(一)flash读写

以这篇未开始我将进行stm32学习整理为期一个月左右完成stm32知识学习整理内容顺序没有一定之规写到哪想到哪想到哪写到哪,主要是扫除自己知识上的盲区完成一些基本外设操作。 以stm32f07为例子进行flash读写操作 stm32flash简介 参考资料正点原子和野火开发手册 …

如何选择传感器输出模式——电流输出还是电压输出?

一 背景及挑战 传感器在汽车测试系统中发挥着采集和传输信息的作用,可称之为汽车的“神经元”。 按照功能可将传感器分为压力传感器、流量传感器、温湿度传感器和电流传感器等。传感器的主要指标是精度、测量范围和响应时间等。在满足指标的情况下,通常…

笔记软件Notability mac中文版软件功能

Notability mac是一款帮助用户备注文件的得力工具,Notability Mac版可用于注释文稿、草拟想法、录制演讲、记录备注等。它将键入、手写、录音和照片结合在一起,便于您根据需要创建相应的备注。 Mac Notability mac中文版软件功能 将手写,照片…

springboot和flask整合nacos,使用openfeign实现服务调用,使用gateway实现网关的搭建(附带jwt续约的实现)

环境准备: 插件版本jdk21springboot 3.0.11 springcloud 2022.0.4 springcloudalibaba 2022.0.0.0 nacos2.2.3(稳定版)python3.8 nacos部署(docker) 先创建目录,分别创建config,logs&#xf…

APISpace 全国快递物流地图轨迹查询API接口案例代码

1.全国快递物流地图轨迹查询接口详解 1.1 接口请求 请求方式:POST请求地址:https://eolink.o.apispace.com/wldtgj1/paidtobuy_api/trace_map请求头: 标签必填说明X-APISpace-Token是鉴权私钥,登陆 APISpace 后在管理后台的[访…

证照之星XE专业版下载专业证件照制作工具

值得肯定的是智能背景替换功能,轻松解决背景处理这一世界难题。不得不提及的是新增打印字体设置,包含字体选择、字号大小、字体颜色等。不同领域的应用证明了万能制作,系统支持自定义证照规格,并预设了17种常用的证件照规格。人所…

紧急:发现NGINX Ingress Controller for Kubernetes中的新安全漏洞

导语 大家好,今天我要向大家紧急报告一则消息:我们在NGINX Ingress Controller for Kubernetes中发现了三个新的安全漏洞!这些漏洞可能被黑客利用,从集群中窃取机密凭据。在本文中,我们将详细介绍这些漏洞的细节&#…

ROCKCHIP ~ Camera 闪光灯

一、闪光灯基本原理 工作模式 Camera flash led分flash和torch两种模式。 flash: 拍照时上光灯瞬间亮一下,电流比较大,目前是1000mA,最大电流不能超过led最大承受能力 torch: 只用于录video或者拿led当手电筒的情况&…

python多环境并存

1. 现况简介 1.1 本人windows所存Python版本 Python 2.7 Python 3.6 Python 3.7 1.2 Python 各版本路径如下 Python 2.7Python 3.6Python 3.7C:\Server\Python27C:\Server\Python36C:\Server\Python37 1.3 系统环境变量配置如下 2. 解决方案 2.1 进入目录 cd C:\Server…

qt5工程打包成可执行exe程序

一、编译生成.exe 1.1、在release模式下编译生成.exe 1.2、建一个空白文件夹package,再将在release模式下生成的.exe文件复制到新建的文件夹中package。 1.3、打开QT5的命令行 1.4、用命令行进入新建文件夹package,使用windeployqt对生成的exe文件进行动…

84.在排序数组中查找元素的第一个和最后一个位置(力扣)

目录 问题描述 代码解决以及思想 知识点 问题描述 代码解决以及思想 class Solution { public:vector<int> searchRange(vector<int>& nums, int target) {int left 0; // 定义左边界int right nums.size() - 1; // 定义右…

2023年10月13日,美国材料与试验协会(ASTM)发布了新版玩具安全标准ASTM F963-23

新标准发布 2023年10月13日&#xff0c;美国材料与试验协会&#xff08;ASTM&#xff09;发布了新版玩具安全标准ASTM F963-23。 主要更新内容 与ASTM F963-17相比&#xff0c;此次更新包括&#xff1a;单独描述了基材重金属元素的豁免情况&#xff0c;更新了邻苯二甲酸酯的管…

【ROS入门】雷达、摄像头及kinect信息仿真以及显示

文章结构 雷达信息仿真以及显示Gazebo仿真雷达配置雷达传感器信息xacro文件集成启动仿真环境 Rviz显示雷达数据 摄像头信息仿真以及显示Gazebo仿真摄像头新建xacro文件&#xff0c;配置摄像头传感器信息xacro文件集成启动仿真环境 Rviz显示摄像头数据 kinect信息仿真以及显示Ga…

基于深度学习网络的美食检测系统matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 % 图像大小 image_size [224 224 3]; num_classes size(VD,2)-1;% 目标类别数量…

可视化 | 数据可视化降维算法梳理

文章目录 &#x1f4da;数据描述&#x1f407;iris&#x1f407;MNIST &#x1f4da;PCA&#x1f407;算法流程&#x1f407;图像描述 &#x1f4da;Kernel-PCA&#x1f407;算法流程&#x1f407;图像描述 &#x1f4da;MDS&#x1f407;算法流程&#x1f407;图像描述 &#…

Linux两条服务器实现相互免密登录

1.准备两台虚拟机&#xff0c;一台充当服务器端&#xff08;server&#xff09;&#xff0c;一台充当客户端&#xff08;client&#xff09; 服务器端&#xff08;server&#xff09;&#xff1a;192.168.75.139 客户端&#xff08;client&#xff09;&#xff1a;192.168.75…

Fegin ----微服务 SpringCloud

FeignClient 是一个注解&#xff0c;用于创建一个声明式的 REST 客户端&#xff0c;用于访问其他服务的 REST API。通过 Feign Client&#xff0c;可以将远程服务的 API 当做本地服务进行调用&#xff0c;Feign Client 能够自动生成 API 客户端的实现类&#xff0c;在使用 API …