I am working on a to-do list using a Java server and Postgres DB - specifically trying to set up a local dev environment using Docker Compose. The server has previously been deployed to Heroku and the database connection works without trouble. I am getting a suitable driver not found error when attempting to establish a connection between the server and DB in Docker.
The Java DB connection code:
public void connectToDatabase() {
try {
String url = System.getenv("JDBC_DATABASE_URL");
conn = DriverManager.getConnection(url);
System.out.println("Database Connection Successful");
} catch (Exception e) {
e.printStackTrace();
}
}
The Java Server Dockerfile:
FROM gradle:7.4-jdk17-alpine
ADD --chown=gradle . /code
WORKDIR /code
EXPOSE 5000
CMD ["gradle", "--stacktrace", "run"]
The image builds without problems. However, when starting with docker compose up, I get the following error: java.sql.SQLException: No suitable driver found for "jdbc:postgresql://tasks-db:5432/test-tasks-db?user=postgres&password=postgres"
The server still runs, just without the DB connection - I can access other endpoints/features.
Docker Compose:
version: "3.9"
services:
java-service:
build:
context: ./EchoServer/
dockerfile: Dockerfile
ports:
- "5000:5000"
environment:
- PORT=5000
- JDBC_DATABASE_URL="jdbc:postgresql://tasks-db:5432/test-tasks-db?user=postgres&password=postgres"
tasks-db:
image: postgres
restart: always
ports:
- "1235:5432"
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
volumes:
- tasks-db:/var/lib/postgresql/data
volumes:
tasks-db:
driver: local
logvolume01: {}
Grateful for any help, have been blocked on this most of the evening.
EDIT: build.gradle dependencies:
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
implementation 'org.json:json:20210307'
implementation 'org.postgresql:postgresql:42.3.1'
}
So after a lot of trial and error, it was a problem with the docker-compose yml, specifically the environmental variable for the DB.
BAD:
JDBC_DATABASE_URL="jdbc:postgresql://tasks-db:5432/test-tasks-db?user=postgres&password=postgres"
This gives DriverManager the url wrapped in quotes. You do not want this.
GOOD:
JDBC_DATABASE_URL=jdbc:postgresql://tasks-db:5432/test-tasks-db?user=postgres&password=postgres
Lack of quotation marks in docker-compose.yml leads to a happy DriverManager.
You don't show how you build your Java application - but you're missing a dependency on the postgres JDBC driver. It does not come with Java, but has to be presented to a Java application in its classpath. Using maven, you would add this dependency: https://mvnrepository.com/artifact/org.postgresql/postgresql/42.3.3
Related
I have the following docker-compose file:
version: '3.1'
services:
localstack:
image: localstack/localstack:0.9.6
ports:
- "4576:4576"
environment:
- SERVICES=sqs:4576
- HOSTNAME_EXTERNAL=localhost
- DEBUG=0
- START_WEB=0
primarydb:
image: mysql:5.6
environment:
MYSQL_USER: test-user
MYSQL_PASSWORD: test-password
MYSQL_DATABASE: testdb
MYSQL_ROOT_PASSWORD: test-password
ports:
- "3318:3306"
And I have the following gradle configuration:
apply plugin: 'docker-compose'
dockerCompose.isRequiredBy(project.tasks.getByName('test'))
dockerCompose {
useComposeFiles = ['docker-compose.yml']
startedServices = ['localstack', 'primarydb']
projectName = "${rootProject.name}"
}
project.tasks.getByName('test').doFirst {
systemProperty 'localstack.sqs.endpoint', "http://localhost:4576"
systemProperty 'mysql.url', "jdbc:mysql://localhost:3318"
}
And I am using the latest docker-compose plugin: com.avast.gradle:gradle-docker-compose-plugin:0.15.1
For some reason, the build works on my friend's Linux machine, but it doesn't work on MacOS 11.4.
When I run ./gradlew composeUp task it just fails with the following error message:
./gradlew composeUp
> Configure project :
2.5.25-SNAPSHOT
> Task :composeUp
Container primarydb-1 Running
Container localstack-1 Recreate
Container localstack-1 Recreated
Container localstack-1 Starting
Container localstack-1 Started
"docker inspect" requires at least 1 argument.
See 'docker inspect --help'.
Usage: docker inspect [OPTIONS] NAME|ID [NAME|ID...]
Return low-level information on Docker objects
> Task :composeUp FAILED
...
Any idea why this plugin doesn't work on a mac but works on my friend's machine?
I faced the same error. Running ./gradle composeUp --stacktrace gave a clue what com.avast.gradle:gradle-docker-compose-plugin:0.15.1 is doing. In essence to does:
docker-compose -p <project name> up
docker-compose -p <project name> config --services and finally
docker-compose -p <project name> ps --services
The third a last step is the one which was failing on me (and is the one currently failing on you.) Repeating the compose-commands manually and having a look into the Docker Desktop UI I could see, that docker-compose did alter my project-name by removing any dots from it. After respecifying
dockerCompose {
[...]
projectName = 'name-without-dots'
}
thus ensuring that docker-compose wont alter the project name, did solve the issue for me.
Your error cause migth still be a different one. Try running ./gradlew composeUp with --stacktrace, --info or even --debug to get a better understanding of what is going wrong.
I have the following docker-compose:
version: '3.1'
services:
db:
container_name: db
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=world
volumes:
- ./mysql-db/:/docker-entrypoint-initdb.d
networks:
- my-network
app:
depends_on:
- db
container_name: app
build: App/
networks:
- my-network
networks:
my-network:
driver: bridge
This builds the mysql image and uses a local file to create the database. I am able to connect to the database through a database client on my host machine. I know the db is running and working with those credentials on port 3306.
App/Dockerfile:
# Build stage
FROM maven:latest AS build
COPY src /app/src
COPY pom.xml /app
# need to assemble to package in plugins
RUN mvn -f /app/pom.xml clean compile assembly:single
# Package stage
FROM openjdk:latest
COPY --from=build /app/target/seMethods-1.0-jar-with-dependencies.jar /usr/local/lib/build.jar
ENTRYPOINT ["java", "-jar", "/usr/local/lib/build.jar"]
This builds the jar file using maven.
App/src/App.java
// sql imports
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
public class App
{
public static void main( String[] args )
{
try {
String dbUrl = "jdbc:mysql://db:3306/world";
Connection con = DriverManager.getConnection(dbUrl,"root","password");
String testStatement = "SELECT * FROM city;";
PreparedStatement preparedTest = con.prepareStatement(testStatement);
ResultSet rs = preparedTest.executeQuery();
while(rs.next()){
System.out.println(rs.getRow());
}
} catch (Exception e) {
// handle any errors
System.out.println(String.format("Error: %s", e));
}
}
}
When my docker-compose runs, the containers are created although my app stops with the following:
Error: com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
How can I connect my db container to app?
You are trying to access a ressource outside your app docker container without having set ports on it. By default as you likely know docker container are insulated from the system, thus you can not access port 3306 from inside the container while you can from your host machine. Add the ports to the docker compose file.
Solved.
When creating the db image, the init file used to generate the inital database took a few seconds to complete. Adding a Thread.sleep() hotfix to the start of my java app allowed the database tables to be created and then I am able to connect.
I would like to run some integrational tests which would include setting up a complete environment with org.testcontainers Docker Compose Module. I am new to Windows and Docker testing, same with the testcontainers.
Using versions:
Docker desktop community: 2.5.0.0
org.testcontainers:testcontainers:1.15.0
org.springframework.boot 2.3.4.
My code looks like the following:
#ClassRule
public static DockerComposeContainer environment = new DockerComposeContainer(
new File("C:\\dev\\myproject\\myapp\\docker-compose\\docker-compose.env.yml"),
new File("C:\\dev\\myproject\\myapp\\docker-compose\\docker-compose.yml"))
.withExposedService("myservice_1", 9999)
.withLocalCompose(true);
My compose files looks something likes this.
services:
myservice:
image: myapp/myservice:latest
hostname: myservice
volumes:
- ../volumeDir:/app/volumeDir
- ../config:/app/config
expose:
- 9999
ports:
- 9999:9999
command: -Dspring.liquibase.enabled=true
networks:
- internet
It looks like some Binding error, the most significant part of the stacktrace:
> java.lang.RuntimeException: java.lang.RuntimeException: org.testcontainers.shaded.com.fasterxml.jackson.databind.exc.ValueInstantiationException:
> Cannot construct instance of `com.github.dockerjava.api.model.Binds`,
> problem: Error parsing Bind
> 'C:\dev\myproject\myapp\volumeDir:/app/volumeDir:rw'
> at [Source: (org.testcontainers.shaded.okio.RealBufferedSource$1); line: 1,
> column: 1369] (through reference chain:
> com.github.dockerjava.api.command.InspectContainerResponse["HostConfig"]->com.github.dockerjava.api.model.HostConfig["Binds"])
> at org.rnorth.ducttape.timeouts.Timeouts.callFuture(Timeouts.java:68)
> at org.rnorth.ducttape.timeouts.Timeouts.doWithTimeout(Timeouts.java:60)
> at org.testcontainers.containers.wait.strategy.WaitAllStrategy.waitUntilReady(WaitAllStrategy.java:53)
> ...
I have tried to change the path to absolute without any difference. Do you have any ideas what can make this bind unparseable?
This error is due to a current issue with Testcontainers and the recent Docker for Windows version. They are already aware of it and a fix seems close to being merged.
UPDATE: Version 1.15.1 is now available that fixes this bug.
I have a Java Spring Boot app which works with a Postgres database. I want to use Docker for both of them. Initially, I created a docker-compose.yml file as given below:
version: '3.2'
services:
postgres:
restart: always
container_name: sample_db
image: postgres:10.4
ports:
- '5432:5432'
environment:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_DB=${POSTGRES_DB}
# APP**
web:
build: .
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/test
expose:
- '8080'
ports:
- '8080:8080'
Then,inside the application.properties file I defined the following properties.
server.port=8080
spring.jpa.generate-ddl=true
spring.datasource.url=jdbc:postgresql://postgres:5432/test
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.flyway.baseline-on-migrate=true
spring.flyway.enabled=true
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = validate
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults: true
Also,I created a Dockerfile in my project directory, which looks like this:
FROM openjdk:8-jdk-alpine
VOLUME /tmp
EXPOSE 8080
RUN mkdir -p /app/
RUN mkdir -p /app/logs/
COPY target/household-0.0.1-SNAPSHOT.jar /app/app.jar
FROM postgres
ENV POSTGRES_PASSWORD postgres
ENV POSTGRES_DB testdb
COPY schema.sql /docker-entrypoint-initdb.d/
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]
I issued these commands and ended up in the error as given below.
mvn clean package
docker build ./ -t springbootapp
docker-compose up
ERROR: for household-appliances_web_1 Cannot start service web: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"java\": executable file not found in $PATH": unknown
ERROR: for web Cannot start service web: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: \"java\": executable file not found in $PATH": unknown
ERROR: Encountered errors while bringing up the project.
Kindly anyone help on this!
I had this error when setting up a Rails appliation for Docker:
My docker-entrypoint.sh file was placed in the root folder of my application with this content:
#!/bin/sh
set -e
bundle exec rails server -b 0.0.0.0 -e production
And in my Dockerfile, I defined my entrypoint command this way:
RUN ["chmod", "+x", "docker-entrypoint.sh"]
ENTRYPOINT ["docker-entrypoint.sh"]
But I was getting the error below when I ran the docker-compose up command:
ERROR: for app Cannot start service app: OCI runtime create failed: container_linux.go:349: starting container process caused "exec: "docker-entrypoint.sh": executable file not found in $
PATH": unknown
Here's how I fixed it:
Specify an actual path for the docker-entrypoint.sh file, that is instead of:
ENTRYPOINT ["docker-entrypoint.sh"]
use
ENTRYPOINT ["./docker-entrypoint.sh"]
This tells docker that the docker-entrypoint.sh file is located in the root folder of your application, you could also specify a different path if the path to your docker-entrypoint.sh is different, but ensure you do not miss out on the ./ prefix to your docker-entrypoint.sh file path definition.
So mine looked like this afterwards:
RUN ["chmod", "+x", "docker-entrypoint.sh"]
ENTRYPOINT ["./docker-entrypoint.sh"]
That's all.
I hope this helps
application.properties file content is irrelevant to question, so you can remove it.
Lets look to your Dockerfile, I will remove irrelevant code
FROM openjdk:8-jdk-alpine
COPY target/household-0.0.1-SNAPSHOT.jar /app/app.jar
FROM postgres
COPY schema.sql /docker-entrypoint-initdb.d/
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]
So you are using multistage building, you just copying file from host to first stage.
As final stage you are using postgres image and telling to set ENTRYPOINT to java, but java does not exists in the postgres image.
What you should change:
You should have postgres containe separated from java container like you have it in docker-compose.yml file and second suggestion use CMD instead of ENTRYPOINT.
Your final Dockerfile should be
FROM openjdk:8-jdk-alpine
COPY target/household-0.0.1-SNAPSHOT.jar /app/app.jar
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app/app.jar"]
The FROM postgres line creates a second image (it is a multi-stage build) that is based on the PostgreSQL database server. Everything above that line is effectively ignored. So your final image is running a second database, and not a JVM.
You don't need this line, and you don't need to extend the database server to run a client. You can delete this line, and the application will start up.
You'll also have to separately get that schema file into the database container. Just bind-mounting the file in volumes: in the docker-compose.yml file is an easy path. If you have a database migration system in your application, running migrations on startup will be a more robust approach.
I am trying to configure this image with LDAP.
In the documentation, they argue you can configure for jdbc with :
SONARQUBE_JDBC_USERNAME: sonar.jdbc.username*
SONARQUBE_JDBC_PASSWORD: sonar.jdbc.password*
SONARQUBE_JDBC_URL: sonar.jdbc.url*
I wonder how I could do the same for LDAP.
Is it possible to use any settings through their environment name ?
Eg: SONAR_LOG_LEVEL=DEBUG
Otherwise, there is inside the container a /opt/sonarqube/conf/sonar.properties
is it there and how should I start editing ?
Another way of achieving what you want is by creating your own sonar.properties file and copying that into the container along with the wrapper.properties.
In the docker-compose.yml
volumes:
- ./sonar-properties:/opt/sonarqube/conf
Otherwise, there is inside the container a /opt/sonarqube/conf/sonar.properties is it there and how should I start editing ?
No, generally what you want to do is possible adding information to your docker-compose file.
In particular in your YML file under the key "enviroment" you can add whatever variable you want.
Here an example of docker-compose.yml file:
version: "3"
services:
registry:
image: registry:2
ports:
- 0.0.0.0:5000:5000
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
REGISTRY_STORAGE_DELETE_ENABLED: "true"
volumes:
- /data/reg:/var/lib/registry
hostname: "myhost.registry"
Than use the compose file to deploy the stack with your custom enviroment.
The solution I found it's to take the configuration file (sonar.properties), to parameter it and to place it in docker-compose.yml :
services:
sonarqube:
image: sonarqube
ports:
- "9000:9000"
networks:
- sonarnet
environment:
- sonar.jdbc.url=
volumes:
- sonarqube_conf:/opt/sonarqube/conf
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
- ./sonar.properties:/opt/sonarqube/conf/sonar.properties
With that, the config file localy is placed in docker.
I hope it's help you