I have a docker compose for MySQL + Spring boot app:
This is how my docker-compose.yaml looks like
version: "3.3"
services:
docker-mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 'pass'
MYSQL_DATABASE: 'test'
volumes:
- /var/lib/mysql
ports:
- 3306:3306
my-app:
build: .
depends_on:
- docker-mysql
ports:
- 8080:8080
restart: on-failure
And this is my Dockerfile:
FROM openjdk:8
EXPOSE 8080
ADD /target/app-0.0.1.jar app.jar
ENTRYPOINT ["java","-jar","app.jar"]
This is the application.properties of my app:
spring.jpa.database=MYSQL
spring.jpa.show-sql=true
spring.datasource.url=jdbc:mysql://docker-mysql:3306/test?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=none
spring.datasource.driverClassName=com.mysql.jdbc.Driver
But when i run the containers with docker-compose up application encounter with access denied:
Access denied for user 'root'#'172.20.0.3' (using password: NO)
In the log file, mysql created with an empty password!
[Warning] root#localhost is created with an empty password !
you following properties should be changed to use the user and pass, you defined in docker-mysql.
spring.datasource.password=pass
Also, add the links option in your spring-boot app.
depends_on:
- docker-mysql
links:
- docker-mysql
I don't think it matters, but the examples on the documentation uses the password without quotes. If above fails, try that as well.
You need mysql access with user root , so Run below command with mysql root user :
GRANT ALL PRIVILEGES ON *.* TO 'root'#'172.20.0.3'
IDENTIFIED BY 'pass'
WITH GRANT OPTION;
FLUSH PRIVILEGES;
Please check!
Related
I was given a multy-steps task and im stuck !!
im trying to connect my Java container to my MYSQL container,but im getting 503 ERROR
HTTP ERROR 503
Problem accessing /. Reason:
Service Unavailable
docker-compose file :
version: "3.3"
services:
lavagna:
build: .
ports:
- "8080:8080"
networks:
- back_net
depends_on:
- my_db
environment:
spring.datasource.url: "jdbc:mysql://my-db:3306/lavagna"
my_db:
image: mysql:5.7
ports:
- "3306:3306"
networks:
- back_net
volumes:
- $PWD/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 123
MYSQL_USER: eyal
MYSQL_PASSWORD: 123
networks:
back_net:
driver: bridge
I got the JAVA src files,i just used maven localy to build it and use target for the Java Dockerfile
java app dockerfile :
FROM openjdk:8-jre-alpine
EXPOSE 8080
COPY ./target/. .
COPY ./entrypoint.sh .
ENV DB_DIALECT MYSQL
ENV DB_URL jdbc:mysql://localhost:3306/lavagna
ENV DB_USER "root"
ENV DB_PASS "123"
ENV SPRING_PROFILE dev
RUN apk update \
&& apk add ca-certificates \
&& update-ca-certificates && apk add openssl
RUN chmod 774 entrypoint.sh
ENTRYPOINT [ "./entrypoint.sh" ]
I think you need a combination of comments and answers given already. Your containers are on the same network, so it appears to boil down to configuration.
In your docker file update your DB_URL to:
ENV DB_URL jdbc:mysql://my_db:3306/lavagna
If you use localhost your container will loopback to itself, and never hit the network.
In your docker-compose yml file, you have a typo in the url, try updating to:
spring.datasource.url: "jdbc:mysql://my_db:3306/lavagna"
As an aside, using depends_on does not wait for the service to be ready. It simply dictates start order as the documentation states:
There are several things to be aware of when using depends_on:
depends_on does not wait for db and redis to be “ready” before starting web - only until they have been started. If you need to wait for a service to be ready...
I am building a Spring Boot application which uses PostgreSQL with docker-compose.
When I run my containers using docker-compose up --build, my Spring Boot application fails to start because it does not find the PostgreSQL container's hostname.
Spring Boot Dockerfile
FROM maven:3.6.3-openjdk-14-slim AS build
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
RUN mvn -f /usr/src/app/pom.xml clean package
FROM openjdk:14-slim
COPY --from=build /usr/src/app/target/server-0.0.1-SNAPSHOT.jar /usr/app/server-0.0.1-SNAPSHOT.jar
EXPOSE 9000
ENTRYPOINT ["java","-jar","/usr/app/server-0.0.1-SNAPSHOT.jar"]
docker-compose.yml
version: '3'
services:
db:
image: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: my_db
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
networks:
- db-network
restart: always
server:
build: './server'
depends_on:
- db
restart: always
ports:
- "9000:9000"
networks:
- db-network
volumes:
- ./server:/server
networks:
db-network:
volumes:
db-data:
application.properties
spring.datasource.url=jdbc:postgresql://db:5432/my_db
spring.datasource.username=postgres
spring.datasource.password=postgres
Error output
Caused by: java.net.UnknownHostException: db
My guess is that docker-compose's virtual network isn't created yet during the build stage of the Spring Boot Dockerfile.
Any idea on how to solve this issue ?
Lots of info here: https://docs.docker.com/compose/networking/
Within the web container, your connection string to db would look like
postgres://db:5432, and from the host machine, the connection string
would look like postgres://{DOCKER_IP}:8001.
What this is saying is db:5432 is fine to use within docker-compose.yaml and the IP address will be passed (not "db"), but using it externally within your application code isn't going to work. You could however pass from docker-compose.yaml db as an application input variable, which your application could fill in in the configuration file. This would enable you then to connect.
Externalising configuration like this is fairly common practice so should be a relatively easy fix.
eg:
Docker-compose.yaml
version: '3'
services:
db:
container_name: db
image: postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: my_db
ports:
- "5432:5432"
volumes:
- db-data:/var/lib/postgresql/data
networks:
- db-network
restart: always
server:
build: './server'
depends_on:
- db
environment:
DB_HOST: db # untested, but there should be a way to pass this in
DB_PORT: 5432
DB_DATABASE: my_db
DB_USER: postgres
DB_PASSWORD: postgres
restart: always
ports:
- "9000:9000"
networks:
- db-network
volumes:
- ./server:/server
networks:
db-network:
volumes:
db-data:
Then have an application.properties file located under src/main/java/resources/application.properties
spring.datasource.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_DATABASE}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
This post completely solved my issue.
It turns out that maven was trying to establish the connection to the database while building the .jar file. All I had to do is modify my Dockerfile with this line RUN mvn -f /usr/src/app/pom.xml clean package -DskipTests.
Please do note while building the images the service will not have access to the database as it is not yet running . Only after the images are built and the containers are running do the services have access . So when you try to pass a host as db , it is not yet available in the build stage . It is available only once the db container starts running .
I'm trying to set up a Spring Boot application that depends on a MySQL database called teste in docker-compose. After issuing docker-compose up, I'm getting:
Caused by: java.net.ConnectException: Connection refused (Connection refused)
I'm running on Linux Mint, my docker-compose version is 1.23.2, my Docker version is 18.09.0.
application.properties
# JPA PROPS
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.datasource.url=jdbc:mysql://db:3306/teste?useSSL=false&serverTimezone=UTC
spring.datasource.username=rafael
spring.datasource.password=password
spring.database.driverClassName =com.mysql.cj.jdbc.Driver
docker-compose.yml
version: '3.5'
services:
db:
image: mysql:latest
environment:
- MYSQL_ROOT_PASSWORD=rootpass
- MYSQL_DATABASE=teste
- MYSQL_USER=rafael
- MYSQL_PASSWORD=password
ports:
- 3306:3306
web:
image: spring-mysql
depends_on:
- db
links:
- db
ports:
- 8080:8080
environment:
- DATABASE_HOST=db
- DATABASE_USER=rafael
- DATABASE_NAME=teste
- DATABASE_PORT=3306
and the Dockerfile
FROM openjdk:8
ADD target/app.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Docker compose always starts and stops containers in dependency order, or sequential order in the file if not given. But docker-compose does not guarantee that it will wait till the dependency container is running. You can refer here for further details. So the problem here is that your database is not ready when your spring-mysql container tries to access the database. So, the recommended solution is you could use wait-for-it.sh or similar script to wrap your spring-mysql app starting ENTRYPOINT.
As example if you use wait-for-it.sh your ENTRYPOINT in your Dockerfile should change to following after copying above script to your project root:
ENTRYPOINT ["./wait-for-it.sh", "db:3306", "--", "java", "-jar", "app.jar"]
And two other important thing to consider here is:
Do not use links they are deprecated you should use user-defined network instead. All services in docker-compose file will be in single user-defined network if you don't explicitly define any network. So you just have to remove the links from compose file.
You don't need to publish the port for docker container if you only use it inside the user-defined network.
I was facing the same issue and in case you do not want to use any custom scripts, this can easily be resolved using health checks along with depends on. A sample using these is as follows:
services:
mysql-db:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=vikas1234
- MYSQL_USER=vikas
ports:
- 3306:3306
restart: always
healthcheck:
test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
timeout: 20s
retries: 10
app:
image: shop-keeper
container_name: shop-keeper-app
build:
context: .
dockerfile: Dockerfile
ports:
- 8080:8080
depends_on:
mysql-db:
condition: service_healthy
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql-db:3306/shopkeeper?createDatabaseIfNotExist=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: vikas1234
Your config looks nice, I would just recommend:
Remove links: db. It has no value in user-defined bridge networking
Remove port exposing for db unless you want to connect from outside docker-compose - all ports are exposed automatically inside user-defined bridge network.
I think the problem is that database container takes more time to start than web. depends_on just controls the order, but does not guarantee you database readiness. If possible, set several connection attempts or put socket-wait procedure in your web container.
I have a simple Java application using a mysql.
This is my docker-compose.yaml:
version: '2.1'
services:
docker-mysql:
image: mysql:latest
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=test2
- MYSQL_PASSWORD=root
ports:
- 3306:3306
my-app:
image: 0935a6b56fe5
depends_on:
- docker-mysql
ports:
- 8080:8080
environment:
- DATABASE_HOST=docker-mysql
- DATABASE_USER=root
- DATABASE_PASSWORD=root
- DATABASE_NAME=test2
- DATABASE_PORT=3306
Image with id 0935a6b56fe5 is a mysql image.
And this is my application.properties:
## Server config
server.port=8080
server.tomcat.uri-encoding=utf-8
## MYSQL JPA
spring.jpa.database=MYSQL
spring.jpa.show-sql=true
spring.datasource.url=jdbc:mysql://localhost:3306/test2?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=true
spring.datasource.validationQuery=SELECT 1
#Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto=none
spring.datasource.driverClassName=com.mysql.jdbc.Driver
When i try docker-compose up application tries to run but it gives me a Connection Refused error.
What is wrong with this?
Most likely this line
spring.datasource.url=jdbc:mysql://localhost:3306/test2?characterEncoding=utf8
should read
spring.datasource.url=jdbc:mysql://docker-mysql:3306/test2?characterEncoding=utf8
because your my-app is running inside of the docker container and localhost is not what you think it is. You can access other docker containers inside of docker-compose with the name of the service you have chosen inside your docker-compose.yml.
Your spring.datasource.url=jdbc:mysql://localhost:3306/test2?characterEncoding=utf8 refers to localhost. Can you try spring.datasource.url=jdbc:mysql://docker-mysql:3306/test2?characterEncoding=utf8
Also the spring.datasource.password= is blank. How do you provide the password?
Hiho
Spring Settings
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url= jdbc:mysql://vetdb:3306/vetdb?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.platform=mysql
spring.datasource.initialize=true
spring.jpa.show-sql=false
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jmx.default-domain=TierarztDatenController
endpoints.jmx.uniquie-names=true
Docker Compose
vetdb:
container_name: vetdb
hostname: vetdb
image: mariadb
restart: always
command: --default-authentication-plugin=mysql_native_password --innodb-flush-method=O_DSYNC --innodb-use-native-aio=0 --log_bin=ON
environment:
MYSQL_ROOT_PASSWORD: ${VET_DB_ROOT_PASSWORD}
MYSQL_DATABASE: ${VET_DB_NAME}
MYSQL_PASSWORD: ${VET_DB_PASSWORD}
MYSQL_ROOT_HOST: '%'
volumes:
# - "${VET_DB_PATH}/mysql-conf:/etc/mysql/conf.d"
- "${VET_DB_PATH}:/var/lib/mysql"
- "${VET_DB_PATH}/mysql-log:/var/log/mysql"
.env
VET_DB_PATH=./dockervolumes/microservices/VET/db
VET_DB_NAME=vetdb
VET_DB_ROOT_PASSWORD=root
VET_DB_PASSWORD=root
Exception: `java.sql.SQLException: null, message from server: "Host '172.23.0.9' is not allowed to connect to this MariaDB server"`
i added MYSQL_ROOT_HOST: '%' to allow everyone to connect to the db but it didnt work
i tried to use a config-file.cnf containing bind-address = 0.0.0.0 but it didnt work
funny thing is everything worked well before i restarted the container today and i didnt change this service in 3 days
i tried see if name/password = root work
$ docker exec -it vetdb bash
root#vetdb:/# mysql -u root -p
Enter password:
ERROR 1045 (28000): Access denied for user 'root'#'localhost' (using password: YES)
but root without password works (inside the container)
root#vetdb:/# mysql -u root
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 21
Server version: 10.3.9-MariaDB-1:10.3.9+maria~bionic-log mariadb.org binary distribution
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]>
if i just remove spring.datasource.password=root
or set it to spring.datasource.password=
then it results in the same exception
what am i doing wrong?
i changed the environment variables to this
environment:
- "MYSQL_ROOT_PASSWORD=${VET_DB_ROOT_PASSWORD}"
- "MYSQL_DATABASE=${VET_DB_NAME}"
- "MYSQL_ROOT_HOST=%"
and deleted everything rerun it and it worked
docker-compose down
docker rm -f $(docker container ls -aq)
docker-compose rm -v
docker volume prune
docker system prune
rm dockerdockervolumes/ -rf
and it worked