You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker运行Spring Boot应用时触发javax.naming.NameNotFoundException

解决Docker中Spring Boot应用的JNDI NameNotFound错误

咱们先把问题根源捋清楚:你本地运行完全正常,但Docker容器里一启动就报NameNotFound,核心原因是Spring Boot自带的内嵌Tomcat默认没开启JNDI支持。你本地能跑,大概率是部署到了外部Tomcat——外部Tomcat的context.xml里已经配置好了JNDI数据源绑定,但Docker里用的是内嵌Tomcat,它根本不知道你定义的jdbc/SubscriptionServicesDataSource在哪,自然就找不到了。

下面是具体的修复步骤:

1. 给内嵌Tomcat手动开启JNDI并绑定数据源

创建一个Tomcat配置类,用来启用JNDI并把你的数据库配置绑定到JNDI上下文里:

import org.apache.tomcat.util.descriptor.web.ContextResource;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jndi.JndiTemplate;

import javax.naming.NamingException;
import javax.sql.DataSource;

@Configuration
public class TomcatJndiConfig {

    @Bean
    public TomcatServletWebServerFactory tomcatFactory() {
        return new TomcatServletWebServerFactory() {
            @Override
            protected void postProcessContext(org.apache.catalina.Context context) {
                // 定义JNDI资源,对应你application.properties里的配置
                ContextResource resource = new ContextResource();
                resource.setName("jdbc/SubscriptionServicesDataSource");
                resource.setType(DataSource.class.getName());
                resource.setProperty("driverClassName", "oracle.jdbc.OracleDriver");
                resource.setProperty("url", "jdbc:oracle:thin:@localhost:21521:webtst");
                resource.setProperty("username", "xxxUnameXXX");
                resource.setProperty("password", "xxxPassxxx");
                resource.setProperty("factory", "org.apache.tomcat.jdbc.pool.DataSourceFactory");
                resource.setProperty("initialSize", "1");
                resource.setProperty("maxActive", "15");

                // 把资源添加到Tomcat的命名上下文
                context.getNamingResources().addResource(resource);
            }
        };
    }

    // 把JNDI数据源注入到Spring容器中供业务使用
    @Bean
    public DataSource subscriptionServicesDataSource() throws NamingException {
        return (DataSource) new JndiTemplate().lookup("java:comp/env/jdbc/SubscriptionServicesDataSource");
    }
}

2. 调整application.properties配置

现在我们已经通过配置类手动绑定了JNDI数据源,你可以把原来的database.datasources系列配置注释掉,或者保留但确保Spring优先使用我们配置类里的DataSource Bean——这样就不会再依赖原来的自定义数据源配置逻辑了。

3. 重新构建并运行Docker镜像

先重新打包构建镜像:

docker build -t it/spring-boot-docker-jdbc .

然后启动容器:

docker run -p 8080:8080 it/spring-boot-docker-jdbc

额外提醒

如果你的数据库是部署在宿主机(本地电脑)上,Docker容器里的localhost指的是容器自身,不是你的电脑。这种情况下,需要把数据库URL里的localhost换成宿主机的IP地址,或者在Docker Desktop环境下用host.docker.internal代替,否则容器会连不上数据库哦!

内容的提问来源于stack exchange,提问作者Itsik Mauyhas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 14:52:33