I'm very new to Docker and I've tried everything I can think of and have gotten desperate. I really hope one of you will know what might be happening. I'm working on a project where I've created a CI pipeline using Jenkins and Docker.
I've tried many things with my spring.datasource.url.
- using the name 'db' as that is what the service is named in docker-compose.yml
- using grep to find the ip address of my docker0 service, my docker container, etc.
- trying localhost as it is
- trying different environment variables in the docker-compose file. (using username and password, not using it.)
- trying environment variables. I can't recall the exact format, but it's something like this: jdbc:mysql://${DATABASE_HOST}:${DATABASE_PORT}/${DATABASE_NAME}?createDatabaseIfNotExist=true&useSSL=false
- trying to install mysql on the EC2 machine.
- Many many other things (30 tries tonight, about 60 last night). If it's on stackoverflow, I probably tried it.
Being such a noob, I'm super likely to just not know something very basic. Honestly I'm about to give up and just try to run it with an H2 database. I would hope that would work easier, but I'm still holding a sliver of hope that this may help.
My project works on my local machine using localhost in my spring.datasource.url.
On EC2 however, I get a variation of 'refused to connect' error.
In spring-boot I get similar errors to these:
- if I try a hard coded name in the connection string for the host:
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source) ~[na:na]
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:89) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.NativeSession.connect(NativeSession.java:120) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:948) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:818) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
... 57 common frames omitted
Caused by: java.net.UnknownHostException: db
at java.base/java.net.InetAddress$CachedAddresses.get(Unknown Source) ~[na:na]
at java.base/java.net.InetAddress.getAllByName0(Unknown Source) ~[na:na]
at java.base/java.net.InetAddress.getAllByName(Unknown Source) ~[na:na]
at java.base/java.net.InetAddress.getAllByName(Unknown Source) ~[na:na]
at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:133) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:63) ~[mysql-connector-java-8.0.27.jar!/:8.0.27]
... 60 common frames omitted
The closest I got was using an IP address in the host slot similar to this:
jdbc:mysql://172.17.0.0:3306/foodboxdb?createDatabaseIfNotExist=true&useSSL=false
I tried 172.17.0.0, 172.18.0.2,172.18.0.3 based on what little I knew to look for:
This approach would timeout, so again, did not work - but didn't give a blatant failure error like the others where it would say the password was wrong, or the host was wrong.
I did find a comment saying that someone changed their RUN command somehow like this:
java -Dspring.profiles.active=dockerembbed,oauth-security -jar myapp.jar
but my command is formatted super differently and I'm not 100% sure how I can try to put that command into my Dockerfile. This is what I have right now:
ENTRYPOINT ["java","-jar","foodbox-service-rest-0.0.1-SNAPSHOT.jar"]
If anyone knows what this person was doing with the -Dspring.profiles.active=dockerembbed
command and the proper way to put it into an ENTRYPOINT command, I'd love to see it.
Anyway, here is my code below. I'm pretty sure this is all the relevant stuff. My github repo is here: https://github.com/samparsons/pg6-backend
Thank you in advance - I really am not sure what else to try at this point!
My application.properties file looks like this:
# Application Properties
server.port=8081
spring.datasource.url=jdbc:mysql://localhost:3306/foodoxdb?createDatabaseIfNotExist=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.defer-datasource-initialization=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.database=mysql
spring.jpa.show-sql=true
My Jenkinsfile Looks like this:
pipeline {
agent any
triggers {
pollSCM('* * * * *')
}
stages {
stage('Docker compose build') {
steps {
echo '----------------- This is a docker-compose phase ----------'
sh 'docker-compose up -d --force-recreate --remove-orphans --build'
}
}
}
}
My docker-compose.yml file looks like this:
version: '3.8'
services:
db:
image: mysql:8
environment:
- MYSQL_ROOT_PASSWORD=
- MYSQL_DATABASE=foodboxdb
- MYSQL_USER=root
- MYSQL_PASSWORD=pw
restart: always
ports:
- 3306:3306
volumes:
- foodboxdb:/var/lib/mysql
foodbox-service-rest:
container_name: foodbox-service-rest
restart: on-failure
image: foodbox-service-rest
build:
context: ./
dockerfile: Dockerfile
depends_on:
- db
ports:
- 8081:8081
environment:
- DATABASE_HOST=db
- DATABASE_USER=root
- DATABASE_PASSWORD=pw
- DATABASE_NAME=foodboxdb
- DATABASE_PORT=3306
volumes:
foodboxdb:
and lastly my Dockerfile looks like this:
# code below is from medium tutorial by Wynn Teo,
https://medium.com/geekculture/dockerizing-a-spring-boot-application-with-maven-122286e9f582
# it has been modified slightly for my use case.
# AS <NAME> to name this stage as maven
FROM maven:3.6.3 AS maven
RUN echo "jenkins ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
EXPOSE 8081
EXPOSE 3306
WORKDIR /usr/src/app
COPY . /usr/src/app
# Compile and package the application to an executable JAR
RUN mvn package -DskipTests
RUN echo "running in root"
RUN ls
RUN echo "running in /usr/src/app"
RUN ls /usr/src/app
RUN echo "running in /usr/src/app/target"
RUN ls /usr/src/app/target
# For Java 11,
FROM adoptopenjdk/openjdk11:alpine-jre
ARG JAR_FILE=foodbox-service-rest-0.0.1-SNAPSHOT.jar
WORKDIR /opt/app
# Copy the foodbox-service-rest-0.0.1-SNAPSHOT.jar from the maven stage to the /opt/app directory of the current stage.
COPY --from=maven /usr/src/app/target/${JAR_FILE} /opt/app/
ENTRYPOINT ["java","-jar","foodbox-service-rest-0.0.1-SNAPSHOT.jar"]
CodePudding user response:
I got it to work. Here is what I did to figure this out.
- Made sure docker-compose ran the service that I wanted to run. If you define the service that needs to run, it will create all the dependencies first. so, I changed my command from
docker-compose up -d --force-recreate --remove-orphans --build
to
docker-compose up -d --force-recreate --remove-orphans --build <PUT_SERVICE_NAME_HERE>
Here is the blurb I read on the docker-compose help docs that gave me this hint: https://docs.docker.com/compose/compose-file/compose-file-v2/#depends_on - Once I did this, I noticed while running
docker ps -a
to observe the status of my containers that I had a new issue - my database kept restarting. Obviously the service won’t work if the DB is down. So, to troubleshoot I found that you can grab container logs in Docker using the following command:docker logs -f <db_container_name>
using this command, I was able to figure out how to get the ‘just make it work’ setup going for my db. Please note - do not copy my environment setup, it’s terrible! I really just need it to work so I can get my project done. As this is for school, they’re not grading on security or even best practices honestly (this program is questionable at best!). - Finally, once the DB was working, I switched back to the format shown here
for my spring.datasource.url:
jdbc:mysql://db:3306/foodboxdb?createDatabaseIfNotExist=true&useSSL=false
using db as the database name, which is the name of the db service that I initiated in the docker-compose.yml file.
Feel free to reuse my repo with the caveats stated above.