Home > Back-end >  AWS EC2, Jenkins, Docker, Spring-boot mysql I suspect my spring.datasource.url is wrong?
AWS EC2, Jenkins, Docker, Spring-boot mysql I suspect my spring.datasource.url is wrong?

Time:02-19

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.

  1. using the name 'db' as that is what the service is named in docker-compose.yml
  2. using grep to find the ip address of my docker0 service, my docker container, etc.
  3. trying localhost as it is
  4. trying different environment variables in the docker-compose file. (using username and password, not using it.)
  5. 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
  6. trying to install mysql on the EC2 machine.
  7. 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.

localhost success on mysql

On EC2 however, I get a variation of 'refused to connect' error.

docker sad times

In spring-boot I get similar errors to these:

  1. 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:

using docker inspect

route on the ec2 root

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.

  1. 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
  2. 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!).
  3. 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.

  • Related