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。
我可能完全错误,但我认为这是值得一试。