How to access an external server folder from a spring boot docker container? - spring-boot

I'm using docker-compose to run spring boot application inside a docker container. A spring boot uses embedded tomcat to run.
There is an external folder on a server (/opt/cp/uploads) with images which I would like to access from a spring boot docker container.
Within the docker-compose.yaml file there are following containers defined:
nginx
mysql
springboot-app
nginx and CloudFlare redirect the domain to the spring app on the port 8080.
I'd like to access images like this:
https://domainname.com/uploads/imageName.png
Using tomcat this was done in server.xml:
<Context docBase="/opt/uploads" path="/uploads"/>
but this option is obviously not available via application.properties with embedded tomcat.
How does one come about this?
My docker-compose.yaml:
version: '3.8'
services:
nginx:
container_name: some-nginx
hostname: nginx
image: nginx:1.19.2-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
restart: unless-stopped
network_mode: host
mysqldb:
image: mysql:8.0.20
hostname: mysqldb
container_name: cp-mysqldb
environment:
- MYSQL_ROOT_PASSWORD=pass1234
- MYSQL_DATABASE=db_name
- MYSQL_USER=root
- MYSQL_PASSWORD=pass1234
ports:
- "3306:3306"
volumes:
- cp-mysqldb-data:/opt/mysql
restart: unless-stopped
springboot-app:
image: openjdk:8
hostname: cp
container_name: cp-springboot
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysqldb:3306/db_name?autoReconnect=true&useSSL=false&useUnicode=yes&characterEncoding=UTF-8&characterSetResults=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
ports:
- "8080:8080"
depends_on:
- mysqldb
volumes:
- cp-springboot-data:/opt/cp
- ./target/cp-springboot-0.0.1-SNAPSHOT.war:/ROOT.war
command: ["java", "-jar",
"-Dspring.profiles.active=prod",
"ROOT.war"]
restart: always
volumes:
cp-springboot-data: {
}
cp-mysqldb-data: {
}

Maybe better use Tomcat for docker image and not OpenJDK.
That way you can setup your Tomcat configuration for the external path
Take a look here: https://medium.com/#iamvickyav/deploying-spring-boot-war-in-tomcat-based-docker-2b689b206496

Actually, this option IS available via application.properties with embedded tomcat:
spring.mvc.static-path-pattern=/uploads/**
spring.resources.static-locations=file:/opt/uploads

Related

docker application not communicate with docker mysql container

I just encountered a problem. I am dockerizing a springboot application with MySQL as a database it is perfectly working in a local setup. But when I try to dockerize the application using docker-compose, MySQL container is working fine and is accessible in my workbench but my application is not able to access it throwing the communication link failure.
This is the compose file I am using:
version: "3.8"
services:
mysqldb:
image: mysql:5.7
restart:unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=baskartest
ports:
- 3307:3306
volumes:
- db:/var/lib/mysql
app:
depends_on:
- mysqldb
build: ./bezkoder-app
restart:on-failure
env_file: ./.env
ports:
- 8084:8080
environment:
SPRING_APPLICATION_JSON: '{
"spring.datasource.url" : "jdbc:mysql://mysqldb:3306/baskartest?useSSL=false",
"spring.datasource.username" : "root",
"spring.datasource.password" : "root",
"spring.jpa.properties.hibernate.dialect" : "org.hibernate.dialect.MySQL5InnoDBDialect",
"spring.jpa.hibernate.ddl-auto" : "update"
}'
volumes:
- .m2:/root/.m2
stdin_open: true
tty: true
MySQL is working fine but my app in services is not able to communicate with it.
Here is what I see:
Any help would be appreciated!
I have done small changes in docker-compose.yml file, please use this one. It is working fine.
version: "3.8"
services:
mysqldb:
image: mysql:5.7
container_name: MYSQL_DB
restart: unless-stopped
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=baskartest
ports:
- 3307:3306
app:
build: ./bezkoder-app
restart: on-failure
ports:
- 8084:8080
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://MYSQL_DB:3306/baskartest
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=root
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
depends_on:
- mysqldb
In my short experience with Docker and containers communicating with eachother, I've found that localhost configuration URL's aren't working. Because one container can't communicatie with another container using just localhost:[PORT].
A lazy way for me to fix this is to work out a static IP address of the machine the containers are running on. Then use this (local) IP address instead of localhost to define the endpoint of the database.
In my situation with Redis I'm doing it like this:
return new LettuceConnectionFactory(new RedisStandaloneConfiguration("192.168.1.201", 6379));
In your situation, you might want to use a Datasource URL like this:
- SPRING_DATASOURCE_URL=jdbc:mysql://[STATIC_IP_OF_MACHINE]:3306/baskartest
*i.e. ...192.168.1.100:3306/baskartest...*

class path resource cannot be resolved to URL when running docker compose

I am trying to create a docker-compose.yml since I have a lot of microservices to bootRun. It works properly when I run them one by one via gradle bootRun but encounter a lot of errors when doing docker-compose up
I want to use my local postgres database.
Here's my docker-compose.yml:
version: '3'
services:
redis:
image: redis:5.0.3-alpine
ports:
- '6379:6379'
rabbitmq:
image: rabbitmq:3.5.3-management
ports:
- "5672:5672"
- "15672:15672"
config-server:
network_mode: host
container_name: config-server
image: config-server:1.0.0-SNAPSHOT
customer-app:
network_mode: host
container_name: customer
image: customer:1.0.0-SNAPSHOT
environment:
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal:5432/demoapp?customer'
depends_on:
- config-server
restart: on-failure
authentication-app:
network_mode: host
container_name: authentication
image: authentication:1.0.0-SNAPSHOT
depends_on:
- config-server
restart: on-failure
admin-app:
network_mode: host
container_name: admin
image: admin:1.0.0-SNAPSHOT
environment:
- 'SPRING_DATASOURCE_URL=jdbc:postgresql://host.docker.internal:5432/demoapp?admin'
depends_on:
- config-server
restart: on-failure
Here's the error (1):
2021-03-23 13:40:36.772 DEBUG 1 --- [ main] o.a.catalina.core.AprLifecycleListener : The Apache Tomcat Native library could not be found using names [tcnative-1, libtcnative-1] on the java.library.path [/usr/java/packages/lib:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib]. The errors reported were [Can't load library: /bin/libtcnative-1.so, Can't load library: /bin/liblibtcnative-1.so, no tcnative-1 in java.library.path: [/usr/java/packages/lib, /usr/lib/x86_64-linux-gnu/jni, /lib/x86_64-linux-gnu, /usr/lib/x86_64-linux-gnu, /usr/lib/jni, /lib, /usr/lib], no libtcnative-1 in java.library.path: [/usr/java/packages/lib, /usr/lib/x86_64-linux-gnu/jni, /lib/x86_64-linux-gnu, /usr/lib/x86_64-linux-gnu, /usr/lib/jni, /lib, /usr/lib]]
Here's the error (2):
Caused by: java.io.FileNotFoundException: class path resource [db/changelog/0.0.1-SNAPSHOT//data/sql/1597842399712-changelog.sql] cannot be resolved to URL because it does not exist
This is the structure of the project:
admin
admin-app
src
main
Dockerfile
java
resources
db.changelog
0.0.1-SNAPSHOT
data.sql
1597842399712-changelog.sql
target
libs
admin-app-1.0.0-SNAPSHOT.jar
Dockerfile:
FROM openjdk:11.0.2-jdk-slim
VOLUME /tmp
COPY target/libs/*.jar app.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","/app.jar"]
Assuming all other things work fine. In your Dockerfile
FROM openjdk:11.0.2-jdk-slim
VOLUME /tmp
RUN mkdir -p /data/sopie/your-project
COPY target/libs/*.jar /data/sopie/your-project/app.jar
EXPOSE 8081
ENTRYPOINT ["java","-jar","app.jar"]

Spring Cloud Consul and Consul Clients dockerized

I have 2 applications, both written using spring boot. Both are running in different docker containers. I also have consul running in a different docker container. I have exposed port 8500 for consul using docker-compose.yml file. So, how do I specify to my spring boot applications where to register themselves, i.e, where is consul running. Do I give the address of the mapped port (port mapped to my local machine), or some other change?
The example I'm using right now: https://github.com/Java-Techie-jt/cloud-consul-service-discovery
Edit:
docker-compose.yml:
version: "2"
services:
consul:
container_name: consul
image: consul
expose:
- "8300"
- "8400"
- "8500"
restart: always
registrator:
container_name: registrator
image: gliderlabs/registrator:master
volumes:
- "/var/run/docker.sock:/tmp/docker.sock"
command: -internal consul://consul:8500
restart: always
depends_on:
- consul
web1:
image: deis/mock-http-server
container_name: web1
expose:
- "8080"
environment:
SERVICE_NAME: "web"
SERVICE_TAGS: "web"
restart: always
depends_on:
- registrator
web2:
image: deis/mock-http-server
container_name: web2
expose:
- "8080"
environment:
SERVICE_8080_NAME: "web"
SERVICE_8080_TAGS: "web"
restart: always
depends_on:
- registrator
haproxy:
build: ./haproxy
container_name: my-haproxy
image: anthcourtney/haproxy-consul
ports:
- 80
depends_on:
- web1
- web2
test:
container_name: test-client
build: ./test
depends_on:
- haproxy
networks:
default:
You can use registrator for your service registry.
Registrator automatically registers and deregisters services for any Docker container by inspecting containers as they come online. Registrator supports pluggable service registries, which currently includes Consul, etcd and SkyDNS 2.
You can run registrator as a container.It will register each port of your application. Below is the sample compose file :-
version: '2'
services:
registrator:
image: "${REGISTRY}gliderlabs/registrator:latest"
command: [
"-ip=<docker-host-ip>",
"-retry-attempts", "100",
"-cleanup",
# "-internal",
"consul://vconsul:8500"
]
official documentation : https://gliderlabs.github.io/registrator/latest/

Access to local database denied through docker container

I am having a problem connecting my compiled Spring-Boot app to the database that I have running on another container on my server.
I have tried different configurations, changing from localhost to the IP address of my server for the connection. I also double checked that the credentials matched by logging in via Adminer. Finally, I did a rebuild of the compose and image files several times to ensure that I have all the latest versions.
Compose file:
version: '3.1'
services:
db:
image: mariadb
restart: always
environment:
MYSQL_ROOT_PASSWORD: mypassword
MYSQL_DATABASE: marketingappdb
ports:
- "3306:3306"
expose:
- 3306
volumes:
- ./mariadbvolume:/var/lib/mariadb
networks:
- marketingapp
adminer:
image: adminer
restart: always
ports:
- "8086:8080"
expose:
- 8086
depends_on:
- db
networks:
- marketingapp
springserver:
image: marketingapp
restart: always
ports:
- "8091:8091"
expose:
- 8091
depends_on:
- db
networks:
- marketingapp
networks:
marketingapp:
Spring Server Image:
FROM openjdk:latest
COPY /marketing-app-final.jar .
EXPOSE 8091
ENTRYPOINT ["java", "-jar", "marketing-app-final.jar"]
Application properties for Spring:
server.port = 8091
spring.datasource.url=jdbc:mariadb://0.0.0.0:3306/marketingappdb
spring.datasource.username=root
spring.datasource.password=mypassword
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
I can connect from my PC to the database using the app from the remote same configuration (obviously replacing localhost with the IP) and don't see why I shouldn't be able to do the same from the actual server. Thanks in advance for any help!
Use the docker dns to connect your spring App to the mariabd:
jdbc:mariadb://db:3306/marketingappdb
Just a few other hints: you don't need to expose port 3306, you already bind it to 3306 on Host (if you just want to use it from within the docker Services you don't need to bind/expose it at all). And the mariabd persistent storage is var/lib/mysql and not var/lib/mariadb

Connecting Spring Cloud Applications in Docker Container

I am attempting to host a Spring Cloud application in Docker containers.The underlying exception is as follows:
search_1 | Caused by: java.lang.IllegalStateException: Invalid URL: config:8888
I understand the reason is because of the URL specified in my config server.
spring.application.name=inventory-client
#spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.uri=config:8888
On my development machine, I am able to use localhost. However, based on a past question (relating to connecting to my database), I learned that localhost is not appropriate in containers. For my database, I was able to use the following:
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=false
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.url=jdbc:postgresql://db:5432/leisurely_diversion
#spring.datasource.url=jdbc:postgresql://localhost:5000/leisurely_diversion
spring.datasource.driver-class-name=org.postgresql.Driver
but this obviously did not work as expected for the configuration server.
My docker-compose file:
# Use postgres/example user/password credentials
version: '3.2'
services:
db:
image: postgres
ports:
- 5000:5432
environment:
POSTGRES_PASSWORD: example
volumes:
- type: volume
source: psql_data
target: /var/lib/postgresql/data
networks:
- app
restart: always
config:
image: kellymarchewa/config_server
networks:
- app
volumes:
- /root/.ssh:/root/.ssh
restart: always
search:
image: kellymarchewa/search_api
networks:
- app
restart: always
ports:
- 8082:8082
depends_on:
- db
- config
- inventory
inventory:
image: kellymarchewa/inventory_api
depends_on:
- db
- config
ports:
- 8081:8081
networks:
- app
restart: always
volumes:
psql_data:
networks:
app:
Both services are running under the same user defined network; how I allow the services to find the configuration service?
Thanks.

Resources