Rust在Docker内部使用actix_web无法实现,为什么?

10
我尝试制作一个Rust程序的Docker容器,让我们来看看。
Docker文件。
FROM debian

RUN apt-get update && \
    apt-get -y upgrade && \
    apt-get -y install git curl g++ build-essential

RUN curl https://sh.rustup.rs -sSf | bash -s -- -y

WORKDIR /usr/src/app

RUN git clone https://github.com/unegare/rust-actix-rest.git

RUN ["/bin/bash", "-c", "source $HOME/.cargo/env; cd ./rust-actix-rest/; cargo build --release; mkdir uploaded"]

EXPOSE 8080

ENTRYPOINT ["/bin/bash", "-c", "echo 'Hello there!'; source $HOME/.cargo/env; cd ./rust-actix-rest/; cargo run --release"]

要运行的命令: docker run -it -p 8080:8080 rust_rest_api/dev

但从外部使用curl curl -i -X POST -F files[]=@img.png 127.0.0.1:8080/upload的结果是curl: (56) Recv failure: Соединение разорвано другой стороной 即通道的另一端拒绝了连接。

但在容器内部:

root@43598d5d9e85:/usr/src/app# lsof -i
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
actix_003   6 root    3u  IPv4 319026      0t0  TCP localhost:http-alt (LISTEN)

但是在没有使用Docker的情况下运行程序可以正常工作,并且可以充分处理来自curl的相同请求。

容器内部:

root@43598d5d9e85:/usr/src/app# curl -i -X POST -F files[]=@i.jpg 127.0.0.1:8080/upload
HTTP/1.1 100 Continue

HTTP/1.1 201 Created
content-length: 70
content-type: application/json
date: Wed, 24 Jul 2019 08:00:54 GMT

{"keys":["uploaded/5nU1nHznvKRGbkQaWAGJKpLSG4nSAYfzCdgMxcx4U2mF.jpg"]}

外部问题是什么?
2个回答

23

如果你和我一样,按照 Actix 网站上的示例进行操作,你可能会编写类似于以下内容或其变体:

fn main() {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(index))
            .route("/again", web::get().to(index2))
    })
    .bind("127.0.0.1:8088")
    .unwrap()
    .run()
    .unwrap();
}

这里的问题是您绑定到了特定的IP地址,而不是使用0.0.0.0来绑定主机容器上的所有IP地址。我曾经遇到过与您相同的问题,并通过更改我的代码解决了它:

fn main() {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(index))
            .route("/again", web::get().to(index2))
    })
    .bind("0.0.0.0:8088")
    .unwrap()
    .run()
    .unwrap();
}

我不确定这是否与您有关,如果没有看到运行服务器的代码,我无法知道。


1
我正在按照actix-web的入门指南操作,最终到达了自动重载部分。该部分建议使用systemfd --no-pid -s http::3000 -- cargo watch -x run,但需要将其更改为http::0.0.0.0:3000以绑定到所有接口。 - Isabaellchen
会有一些变体的.bind("host.docker.internal:8088")实际上会起作用吗?并且仍然限制只有真正的本地主机才能访问Actix吗?这不起作用,将其绑定到Docker网关IP也不行。 - cloudsurfin

6
为了补充John所说的,我在这种情况下必须使用一个元组:.bind( ("0.0.0.0", 8088) )

这不是一个答案,应该是对已批准答案的评论。 - hB0
5
@hB0,很抱歉,我希望我能做翻译工作,但评论功能只对声望达到50的用户开放。 - nlko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接