Docker容器之间的JDBC连接(docker-compose)

我尝试将运行在tomcat 8上的Web应用程序连接到Oracle数据库。 它们都作为Docker容器运行:

泊坞窗,compose.yml:

version: "3" services: appweb: build: ./app image: "servlet-search-app:0.1" ports: - "8888:8080" links: - appdb environment: - DATA_SOURCE_NAME="jdbc:oracle:thin:@appdb:1521/XE" appdb: build: ./db image: "servlet-search-db:0.1" ports: - "49160:22" - "1521:1521" - "8889:8080" 

我的oracle数据库镜像的Dockerfile(build:./db):

 FROM wnameless/oracle-xe-11g ADD createUser.sql /docker-entrypoint-initdb.d/ ENV ORACLE_ALLOW_REMOTE=true 

Tomcat映像的Dockerfile(build:./app)

 FROM tomcat:8.0.20-jre8 COPY servlet.war /usr/local/tomcat/webapps/ COPY ojdbc14-1.0.jar /usr/local/tomcat/lib/ 

所以应用程序按预期启动,但在尝试连接到数据库时引发exception:

 java.lang.IllegalStateException: java.sql.SQLException: Io exception: Invalid connection string format, a valid format is: "host:port:sid" org.se.lab.ui.ControllerServlet.createConnection(ControllerServlet.java:115) org.se.lab.ui.ControllerServlet.handleSearch(ControllerServlet.java:78) org.se.lab.ui.ControllerServlet.doPost(ControllerServlet.java:53) org.se.lab.ui.ControllerServlet.doGet(ControllerServlet.java:38) javax.servlet.http.HttpServlet.service(HttpServlet.java:618) javax.servlet.http.HttpServlet.service(HttpServlet.java:725) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 

现在问题似乎很明显,但是当我修复DATA_SOURCE_NAMEstring到:

 DATA_SOURCE_NAME="jdbc:oracle:thin:@appdb:1521:XE" 

我得到以下例外:

 java.lang.IllegalStateException: java.sql.SQLException: Listener refused the connection with the following error: ORA-12505, TNS:listener does not currently know of SID given in connect descriptor The Connection descriptor used by the client was: appdb:1521:XE" org.se.lab.ui.ControllerServlet.createConnection(ControllerServlet.java:115) org.se.lab.ui.ControllerServlet.handleSearch(ControllerServlet.java:78) org.se.lab.ui.ControllerServlet.doPost(ControllerServlet.java:53) org.se.lab.ui.ControllerServlet.doGet(ControllerServlet.java:38) javax.servlet.http.HttpServlet.service(HttpServlet.java:618) javax.servlet.http.HttpServlet.service(HttpServlet.java:725) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 

现在我试图找出他们中的哪一个应该工作。 因此,我只开始了DB容器:

 docker build -t dbtest . docker run -it -d --rm -p 1521:1521 --name dbtest dbtest docker inspect dbtest | grep IPAddress >> "IPAddress": "172.17.0.4" 

接下来,我尝试连接sqlplus:

 sqlplus system/oracle@172.17.0.4:1521/XE # works sqlplus system/oracle@172.17.0.4:1521:XE #ERROR: ORA-12545: Connect failed because target host or object does not exist 

所以有什么问题? 由于docker-compose文件中的链接,tomcat容器可以将“appdb”parsing为容器的IP。

这是应该build立连接的代码:

 protected Connection createConnection() { String datasource = System.getenv("DATA_SOURCE_NAME"); try { // debug InetAddress address = null; try { address = InetAddress.getByName("appdb"); System.out.println(address); // resolves in appdb/10.0.0.2 System.out.println(address.getHostAddress()); // resolves in 10.0.0.2 } catch (UnknownHostException e) { e.printStackTrace(); } Class.forName("oracle.jdbc.driver.OracleDriver"); return DriverManager.getConnection(datasource, "system", "oracle"); } catch (SQLException | ClassNotFoundException e) { throw new IllegalStateException(e); } } 

最后这里是tnsnames.ora文件:

  cat $ORACLE_HOME/network/admin/tnsnames.ora # tnsnames.ora Network Configuration File: XE = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = fcffb044d69d)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE) ) ) EXTPROC_CONNECTION_DATA = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC_FOR_XE)) ) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO) ) ) 

谢谢!

oracle默认侦听器将configuration的主机parsing为错误的IP地址:

vim $ ORACLE_HOME / network / admin / listener.ora:

 SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = /u01/app/oracle/product/11.2.0/xe) (PROGRAM = extproc) ) ) LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC_FOR_XE)) (ADDRESS = (PROTOCOL = TCP)(HOST = f4c4a3638c11)(PORT = 1521)) ) ) DEFAULT_SERVICE_LISTENER = (XE) 

HOST值是Docker容器标识。 如果我们看看/ etc / hosts,它在docker-compose链接中的服务链接正确设置:

 10.0.0.5 f4c4a3638c11 

它也从tomcat容器中正确parsing

 ping f4c4a3638c11 PING f4c4a3638c11 (10.0.0.5): 56 data bytes ... 

如果我尝试使用其他接口(主机系统的docker接口)的IP地址进行连接,则从Web应用程序到数据库的连接将工作

 String datasource = "jdbc:oracle:thin:@172.17.0.4:1521:XE"; 

所以解决scheme是configuration侦听器来侦听正确的IP地址

 (ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.5)(PORT = 1521)) 

现在这个连接string工作:

 jdbc:oracle:thin:@appdb:1521:XE 

我将这个行为报告给wnameless / oracle-xe-11g作为一个bug

对不起,这不是一个明确的答案。 让我们把它当作长久的评论:)

您的设置对于我来说是非常复杂的,但是您的错误信息很有趣:

 The Connection descriptor used by the client was: appdb:1521:XE" ... 

它看起来像环境价值appdb:1521:XE 。 如果你尝试硬编码,那么如何?

 String datasource = "jdbc:oracle:thin:@appdb:1521/XE"; 

如果这样的话,那么可能需要以某种方式逃避你的DATA_SOURCE_NAME环境variables。

我可能完全错误,但我认为这是值得一试。

Interesting Posts