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支持),此模式下无需端口映射,直接使用本地地址:
对应的JDBC URL改为:oracle.withNetworkMode("host");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
相关产品推荐
相关产品推荐

