'Docker Compose Java Application & MySql Connection Problem with JDBC
When implementing a Java application in a docker container and a MySQL database configured in its own docker container together with Docker Compose, the following error always occurs in the Java application when creating a connection to the database with jdbc:
currency_server_v0_1 | com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
currency_server_v0_1 |
currency_server_v0_1 | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
currency_server_v0_1 | at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
currency_server_v0_1 | at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246)
currency_server_v0_1 | at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:197)
currency_server_v0_1 | at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:677)
currency_server_v0_1 | at java.sql/java.sql.DriverManager.getConnection(DriverManager.java:228)
currency_server_v0_1 | at Test.main(Test.java:22)
currency_server_v0_1 | Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
currency_server_v0_1 |
currency_server_v0_1 | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
currency_server_v0_1 | at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
currency_server_v0_1 | at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:78)
currency_server_v0_1 | at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
currency_server_v0_1 | at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
currency_server_v0_1 | at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
currency_server_v0_1 | at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
currency_server_v0_1 | at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
currency_server_v0_1 | at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
currency_server_v0_1 | at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167)
currency_server_v0_1 | at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:91)
currency_server_v0_1 | at com.mysql.cj.NativeSession.connect(NativeSession.java:144)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:956)
currency_server_v0_1 | at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:826)
currency_server_v0_1 | ... 6 more
currency_server_v0_1 | Caused by: java.net.ConnectException: Connection refused
currency_server_v0_1 | at java.base/sun.nio.ch.Net.connect0(Native Method)
currency_server_v0_1 | at java.base/sun.nio.ch.Net.connect(Net.java:576)
currency_server_v0_1 | at java.base/sun.nio.ch.Net.connect(Net.java:565)
currency_server_v0_1 | at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:588)
currency_server_v0_1 | at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:333)
currency_server_v0_1 | at java.base/java.net.Socket.connect(Socket.java:645)
currency_server_v0_1 | at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:155)
currency_server_v0_1 | at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:65)
currency_server_v0_1 | ... 9 more
currency_server_v0_currency_server_v0_1 exited with code 0
The corresponding Docker files and Java code look like this: docker-compose.yml: version: "3.7"
services:
currency_server_v0:
build: .
ports:
- 8080:8080
depends_on:
- mysqldb
networks:
currency-mysql:
mysqldb:
image: mysql:5.7
container_name: mysqldb
ports:
- 3306:3306
networks:
currency-mysql:
volumes:
- db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=currency_server_db
- MYSQL_USER= admin
- MYSQL_PASSWORD= admin
volumes:
db:
networks:
currency-mysql:
JDBC Connection in Java:
try (Connection conn = DriverManager.getConnection(
"jdbc:mysql://mysqldb:3306/currency_server_db", "root", "root");
Statement stmt = conn.createStatement();
) {
String sql = "CREATE TABLE TEST " +
"(id INTEGER not NULL, " +
" PRIMARY KEY ( id ))";
stmt.executeUpdate(sql);
System.out.println("Created table in given database...");
} catch (SQLException e) {
e.printStackTrace();
}
Dockerfile:
FROM openjdk:16-alpine3.13
COPY target/currency_server_v0-1.0-SNAPSHOT-jar-with-dependencies.jar app.jar
ENTRYPOINT ["java","-jar", "app.jar"]
Does anyone have or know this problem? Thanks for your answers.
Solution 1:[1]
Your service starts faster than MySql despite depends_on which does not know how to check if a container is ready to accept connections. You could implement a wait behaviour in your service Dockerfile or you could do something like this in Java:
public static void main(final String[] args) {
waitForServer("mysqldb", 3306, 10_000);
}
public static void waitForServer(String host, int port, int timeout) {
long start = System.currentTimeMillis();
while (portUnavailable(host, port)) {
System.out.println("Waiting for port to open: " + port);
if (System.currentTimeMillis() - start > timeout) {
throw new Error("Timeout waiting for port to open: " + port);
}
}
}
private static boolean portUnavailable(String host, int port) {
try (Socket s = new Socket(host, port)) {
return false;
} catch (Exception e) {
return true;
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Delta George |
