Docker容器之间的JDBC连接(docker-compose)
我尝试将运行在tomcat 8上的web应用程序连接到oracle数据库。他们都运行的Docker容器:Docker容器之间的JDBC连接(docker-compose)
泊坞窗,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"
Dockerfile我预言的DB图像(编译:./db):
FROM wnameless/oracle-xe-11g
ADD createUser.sql /docker-entrypoint-initdb.d/
ENV ORACLE_ALLOW_REMOTE=true
Dockerfile的Tomcat image(build:./app)
FROM tomcat:8.0.20-jre8
COPY servlet.war /usr/local/tomcat/webapps/
COPY ojdbc14-1.0.jar /usr/local/tomcat/lib/
因此,应用程序按预期启动,但在尝试连接时引发异常t Ø数据库:
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_NAME字符串:
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/[email protected]:1521/XE # works
sqlplus system/[email protected]:1521:XE #ERROR: ORA-12545: Connect failed because target host or object does not exist
那么,有什么问题呢?由于docker-compose文件中的链接,tomcat容器可以将“appdb”解析为容器的IP。
这里应该建立连接的代码:
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)
)
)
谢谢!
神谕默认监听解决了配置的主机的IP地址错误:
VIM $ ORACLE_HOME /网络/管理/监听器。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容器ID。如果我们看一下/ etc/hosts文件被正确设置在泊坞窗,撰写链接服务链接:
10.0.0.5 f4c4a3638c11
它得到也正确地从Tomcat容器解决
ping f4c4a3638c11
PING f4c4a3638c11 (10.0.0.5): 56 data bytes
...
如果我尝试与其他接口的IP地址,这是从主机系统的泊坞窗接口连接,从Web应用程序与数据库的连接工作
String datasource = "jdbc:oracle:thin:@172.17.0.4:1521:XE";
因此,解决办法是配置听者听正确的IP地址
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.0.5)(PORT = 1521))
现在这个连接字符串的工作原理:
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
环境变量。
我可能是完全错误的,但我认为这是值得一试。
感谢您的回复,我也这么认为。但是,这似乎是常见的错误信息。 – CaptainMango
我想你将不得不尝试连接没有码头图像/容器首先确保与数据库连接建立? – JBone