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

Testcontainers Oracle XE本地正常,GitLab CI+Podman环境报ORA-12514求助

问题描述

本地使用Testcontainers搭配Oracle XE运行集成测试一切正常,但在GitLab CI的Kubernetes执行器环境中,以Podman作为Docker服务时,测试抛出以下错误:

java.sql.SQLRecoverableException: Listener refused the connection with the following error: ORA-12514, TNS:listener does not currently know of service requested in connect descriptor

GitLab CI配置

services:
  - name: mycompanyimage/buildah-podman:1.21.0-3.2.3-companycerts-3
    alias: docker
    command: [ "sudo", "podman", "system", "service", "--time=0", "tcp:0.0.0.0:2375" ]

variables:
  DOCKER_HOST: "tcp://docker:2375"
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: ""
  TESTCONTAINERS_RYUK_DISABLED: "true"
  TESTCONTAINERS_CHECKS_DISABLE: "true"

相关日志

  • Testcontainers启动日志:
Container is started (JDBC URL: jdbc:oracle:thin:@docker:1521/xe)
  • Oracle监听器日志:
Default Service           XE

补充信息

  • 从Oracle容器提取的tnsnames.ora内容:
XE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XE)
    )
  )
 
XEPDB1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = XEPDB1)
    )
  )
 
FREE =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = FREE)
    )
  )
 
FREEPDB1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 0.0.0.0)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = FREEPDB1)
    )
  )
 
EXTPROC_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC_FOR_XE))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
      (PRESENTATION = RO)
    )
  )
  • 直接将Oracle作为GitLab流水线的service container配置时无任何错误,问题仅与Testcontainers的使用场景相关。
  • 限制条件:无法更改GitLab执行器,不能使用dind镜像,公司环境禁用Docker。

解决建议

1. 修正Testcontainers的Oracle容器配置与JDBC URL构造

Podman在K8s执行器环境下的端口转发、服务名解析逻辑与本地Docker存在差异,需显式指定配置:

  • 在Testcontainers代码中强制指定Oracle服务名,并显式映射端口:
    OracleContainer oracle = new OracleContainer("gvenzl/oracle-xe:latest")
        .withExposedPorts(1521)
        .withEnv("ORACLE_SERVICE", "XE")
        .withEnv("ORACLE_PDB", "XEPDB1");
    
  • 手动构造JDBC URL,避免Testcontainers自动推断的地址可能存在的问题:
    String jdbcUrl = String.format("jdbc:oracle:thin:@%s:%d/XE", oracle.getHost(), oracle.getMappedPort(1521));
    

2. 调整Testcontainers网络配置适配Podman/K8s环境

Podman在K8s执行器中的网络模式可能导致容器间连通性问题,可尝试以下配置:

  • 在GitLab CI变量中添加TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE,适配Podman的socket路径:
    variables:
      # 新增变量
      TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE: "/var/run/docker.sock"
    
  • 启用host网络模式(需Podman支持),此模式下无需端口映射,直接使用本地地址:
    oracle.withNetworkMode("host");
    
    对应的JDBC URL改为:jdbc:oracle:thin:@localhost:1521/XE

3. 延长Oracle容器启动等待时长

GitLab CI的K8s执行器资源可能受限,Oracle容器启动后服务注册到监听器需要更长时间:

  • 添加自定义等待策略,监听监听器日志确认服务注册完成:
    import org.testcontainers.containers.wait.strategy.Wait;
    import java.time.Duration;
    
    oracle.waitingFor(Wait.forLogMessage(".*Default Service.*XE.*", 1)
        .withStartupTimeout(Duration.ofMinutes(5)));
    
  • 或直接延长默认启动超时时间:
    oracle.withStartupTimeout(Duration.ofMinutes(5));
    

4. 验证Podman容器的网络可达性

在GitLab CI流水线中添加前置步骤,排查网络与服务注册问题:

# 查看运行的Oracle容器详情
podman ps
# 测试job容器到Oracle容器的端口连通性
telnet docker 1521
# 执行Oracle监听器状态查询,确认XE服务已注册
podman exec $(podman ps -q --filter ancestor=gvenzl/oracle-xe:latest) lsnrctl status

5. 使用Oracle官方镜像并显式配置参数

改用Oracle官方镜像,避免第三方镜像的默认配置适配问题:

OracleContainer oracle = new OracleContainer("container-registry.oracle.com/database/express:latest")
    .withEnv("ORACLE_SID", "XE")
    .withEnv("ORACLE_PDB", "XEPDB1")
    .withEnv("ORACLE_PASSWORD", "your-test-password");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 01:29:51