Docker警告:使用主机网络模式时,发布的端口将被丢弃。

27

我有一个Springboot应用程序,已经被Docker化了。 它在端口8081上公开,可以按预期访问它。

http://<ipaddress>:8081

问题

在Docker容器中的Springboot应用程序需要连接到同一主机上(不在容器中)的Postgres数据库,但似乎它没有访问主机网络的权限。

连接到localhost:5432被拒绝

Docker命令:

docker run -t --rm -d -p 8081:8081 --name nexct-approval-service-container nexct-approval-service-image

我了解到如果想要连接网络,可以使用以下方法:

--network host 

然而,之后它停止允许访问应用程序本身(端口8081):
WARNING: Published ports are discarded when using host network mode

问题

如何允许访问端口8081的SpringBoot应用程序,并允许Springboot应用程序访问主机网络以便连接到数据库?


更新

我的数据库连接在Spring Boot中定义:

application.properties

spring.datasource1.driver-class-name=org.postgresql.Driver
spring.datasource1.jdbc-url=jdbc:postgresql://localhost:5432/pims
spring.datasource1.username=postgres
spring.datasource1.password=

MultipleDBConfig.java

@Configuration
@ComponentScan(basePackages = "com.nexct")
public class MultipleDBConfig {

    @Bean(name = "datasource1")
    @ConfigurationProperties("spring.datasource1")
    @Primary
    public DataSource dataSource1(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "datasource2")
    @ConfigurationProperties("spring.datasource2")
    public DataSource dataSource2(){
        return DataSourceBuilder.create().build();
    }
}

2
你有检查过这个链接吗:https://dev59.com/xF4c5IYBdhLWcg3wUI4N - mangusta
链接@mangusta上建议的确实有效。基本上,主机上的服务可以通过主机IP访问。使用ifconfig或ipconfig命令,您可以找到主机IP,然后进行相同操作。 - sandeepkunkunuru
3个回答

20
在我的服务中,我用host.docker.internal 替换了对localhost的引用,并且我能够使用-p发布容器的端口并连接到本地主机上的服务,而无需使用--network host。我的服务引用了一个包含主机名的.env文件,因此我只需创建另一个更新了主机名的.env文件即可。

非常感谢。在我的 Mac 上也可以运行。 - Long Nguyen
你是如何替换本地主机的引用的?你运行了命令host.docker.internal吗? - palamuGuy
.env文件中引用了localhost,所以我只是替换了它。代码使用了指向适当域名的环境变量。 - user2233706

13

在网络模式为host时,无法发布端口。

注意:当使用主机模式网络时,容器没有自己的IP地址,因此端口映射不会生效-p、--publish、-P和--publish-all选项将被忽略,并产生警告:

主机网络

如何允许对端口8081上的SpringBoot应用程序进行访问,并允许Springboot应用程序访问主机网络以连接到数据库?

然而,通过将主机网络分配给容器,仍然无法访问主机网络。要访问主机网络,可以使用主机IP或使用mac和window的特殊DNS。

host.docker.internal:DB_PORT

如果您使用Linux,则可以使用主机IP

HOST_IP:DB_PORT

或者您可以尝试(在Ubuntu上有效)

docker run -it --rm -e HOST_IP=$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p') image_name
现在在您的应用程序中使用HOST_IP作为主机名。

谢谢您的回答。我在一台Linux机器上。我应该在哪里配置HOST_IP:DB_PORT?是在docker run命令中吗? - Richard
1
这是您的主机IP。使用ifconfighostname -I命令查看。您可能有多个IP地址(例如一个用于以太网,一个用于WiFi)。请注意,您的数据库服务器必须在此IP地址或0.0.0.0(所有主机)上进行监听,否则您可能无法连接(如果DB侦听localhost,则您将无法连接)。 - Pierre B.
1
docker run -it --rm -e HOST_DB=$(ip -o route get to 8.8.8.8 | sed -n 's/.src ([0-9.]+)./\1/p') image_name。看到这里,将IP传递给环境变量HOST_DB,并在应用程序中使用此环境变量连接DB,或者在应用程序中使用IP,如果您不想在运行命令中设置。 - Adiii
你的数据库连接是什么样子的?应该使用 getenv.HOST_DB。看起来你在代码中仍然没有使用有效的值? - Adiii
1
将应用程序属性中的localhost替换为ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p'返回的IP。 - Adiii
显示剩余5条评论

5
你需要修改连接字符串中的 localhost 为:172.17.0.1,这是容器网络的IP地址。然后再次检查。

without : in the between - Thanh Nguyen Van
开放它,将 --network host 从 dockerfile 中移除,然后重新运行。 - Thanh Nguyen Van
如果我删除 --network host,那么我就可以访问端口8081上的rest api。但是当Spring Boot应用程序尝试连接到数据库时,如果 spring.datasource1.jdbc-url=jdbc:postgresql://localhost:5432/pims,我会得到 connection refused。然而,如果 spring.datasource1.jdbc-url=jdbc:postgresql://172.17.0.1:5432/pims,那么我会得到 No route to host - Richard
2
你能执行命令:docker inspect container_id 然后获取:"Gateway": "x.x.x.x",将 x.x.x.x 替换为 172.17.0.1 吗? - Thanh Nguyen Van
我怎么知道container_id是什么?我尝试了以下命令:docker inspect nexct-approval-service-container,但是返回错误信息:Error: No such object: nexct-approval-service-container - Richard
显示剩余7条评论

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