Cannot access to spring boot application running with docker-compose - spring-boot

I have a simple application composed by spring boot and mariadb. OS is mac OS, and using IntelliJ as IDE. Dockerfile for spring app is below;
FROM openjdk:14-jdk-alpine
RUN mkdir /app
WORKDIR /app
VOLUME /app
ENV JAR_TARGET "my_app-0.0.1-SNAPSHOT.jar"
ENTRYPOINT ["sh","-c","java -jar ./build/libs/${JAR_TARGET}"]
And docker-compose.yml which refers Dockerfile above is like;
version: "3.3"
services:
app:
build: docker/.
ports:
- "8080:8080"
volumes:
- .:/app
depends_on:
- db
environment:
spring.datasource.driverClassName: "org.mariadb.jdbc.Driver"
spring.datasource.url: "jdbc:mariadb://db:3306/my_app_db"
spring.datasource.username: "user"
spring.datasource.password: "password"
server.port: 8080
server.address: 127.0.0.1
db:
image: mariadb
ports:
- "3306:3306"
environment:
- MYSQL_DATABASE=my_app_db
- MYSQL_USER=user
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=rootpassword,
By typing the command docker-compose up --build into terminal, docker-compose starts runnning and spring boot app "my_app" also seems to be running with the log ... Started MyAppApplicationKt in 25.161 seconds (JVM running for 27.301).
However, when I try to access that spring app by calling http://localhost:8080/api, it is not responding. For example, when I do curl with the address, it is timed out every time. I checked with IP 127.0.0.1 too, but it resulted in the same; not responding.
When I see docker container ps, both spring app and mariadb look like successfully running as below.
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b6abb2d330d9 my_app "sh -c 'java -jar -D…" 5 minutes ago Up 5 minutes 0.0.0.0:8080->8080/tcp my_app_1
fb3b3cad20ad mariadb "docker-entrypoint.s…" 17 minutes ago Up 5 minutes 0.0.0.0:3306->3306/tcp my_app_db_1
I cannot understand why this spring app is not responding when I reach http://localhost:8080/api. Any help would be really appreciated. Thank you for reading!

David Maze's comment did solve my problem. The docker container was not listening on 127.0.0.1 because I set inside process address on 127.0.0.1. I changed server.address in docker-compose.yml to 0.0.0.0, and it started listening on 127.0.0.1 for outside access.
Thank you so much for all comments, especially David who saved me!

Related

Connecting to a Mongo container from Spring container

I have a problem here that I really cannot understand. I already saw few topics here with the same problem and those topics was successfully solved. I basically did the same thing and cannot understand what I'm doing wrong.
I have a Spring application container that tries to connect to a Mongo container through the following Docker Composer:
version: '3'
services:
app:
build: .
ports:
- "8080:8080"
links:
- db
db:
image: mongo
volumes:
- ./database:/data
ports:
- "27017:27017"
In my application.properties:
spring.data.mongodb.uri=mongodb://db:27017/app
Finally, my Dockerfile:
FROM eclipse-temurin:11-jre-alpine
WORKDIR /home/java
RUN mkdir /home/java/bar
COPY ./build/libs/foo.jar /home/java/bar/foo.jar
CMD ["java","-jar", "/home/java/bar/foo.jar"]
When I run docker compose up --build I got:
2022-11-17 12:08:53.452 INFO 1 --- [null'}-db:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server db:27017
Caused by: java.net.UnknownHostException: db
Running the docker compose ps I can see the mongo container running well, and I am able to connect to it through Mongo Compass and with this same Spring Application but outside of container. The difference running outside of container is the host from spring.data.mongodb.uri=mongodb://db:27017/app to spring.data.mongodb.uri=mongodb://localhost:27017/app.
Also, I already tried to change the host for localhost inside of the spring container and didnt work.
You need to specify MongoDB host, port and database as different parameters as mentioned here.
spring.data.mongodb.host=db
spring.data.mongodb.port=27017
spring.data.mongodb.authentication-database=admin
As per the official docker-compose documentation the above docker-compose file should worked since both db and app are in the same network (You can check if they are in different networks just in case)
If the networking is not working, as a workaround, instead of using localhost inside the spring container, use the server's IP, i.e, mongodb://<server_ip>:27017/app (And make sure there is no firewall blocking it)

java.net.UnknownHostException: host.docker.internal: Name or service not known on AWS EC2

I ran into this "java.net.UnknownHostException: host.docker.internal: Name or service not known" problem when deploying a dockerized spring boot application on an AWS EC2 T2.micro instance. The spring boot application failed to start because of this error.
But the weird part is, I did not use the variable "host.docker.internal" anywhere in my application: not in the code, not in the yaml file, not in the .env file:
$ sudo grep -Rl "host.docker.internal" ~
/home/ec2-user/.bash_history
And when I run the following command it shows nothing but previous command to search for it:
$ cat /home/ec2-user/.bash_history | grep "host.docker.internal"
Locally I am using Windows 10 for development, and I can successfully bring up the stack with docker-compose.
Here is the EC2 instance OS version info:
$ cat /etc/*release
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
Amazon Linux release 2 (Karoo)
And here is the docker-compose file that I used on the EC2 instance:
version: '2'
services:
backend:
container_name: backend
image: 'dockerhubuser/backend:0.0.4'
ports:
- '8080:8080'
volumes:
- /var/log/backend/logs:/var/log/backend/logs
- ./backend-ssl:/etc/ssh/backend
env_file:
- .env
depends_on:
- mysql
- redis
redis:
container_name: redis
image: 'redis:alpine'
ports:
- '6379:6379'
volumes:
- $PWD/redis/redis-data:/var/lib/redis
- $PWD/redis/redis.conf:/usr/local/etc/redis/redis.conf
mysql:
container_name: mysql
image: 'mysql:8.0.21'
ports:
- '3306:3306'
environment:
MYSQL_DATABASE: dbname
MYSQL_USER: dbuser
MYSQL_PASSWORD: dbpass
MYSQL_ROOT_PASSWORD: dbrootpass
volumes:
- ./my_volume/mysql:/var/lib/mysql
volumes:
my_volume:
And here is my .env file on the EC2 instance:
SERVER_PORT=8080
KEY_STORE=/etc/ssh/backend/keystore.p12
KEY_STORE_PASSWORD=keystorepass
REDIS_HOST=redis
REDIS_PORT=6379
DB_HOST=mysql
DB_PORT=3306
DB_USERNAME=dbuser
DB_PASSWORD=dbpass
I am pretty sure that this .env file is being used when bringing up the stack with "docker-compose up" because I can see the SERVER_PORT in the log matches this file when I change it.
2021-01-02 20:55:44.870 [main] INFO o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (https)
But I keep getting the error complaining about "host.docker.internal".
Here are things that I have tried but not working:
Hard-code the db host in property spring.datasource.url in application.yml
Add the following entry to /etc/hosts file (see https://stackoverflow.com/a/48547074/1852496)
172.17.0.1 host.docker.internal
Add the following entry to /etc/hosts file, where "ip-172-31-33-56.us-east-2.compute.internal" is what I got when running command "echo $HOSTNAME"
ip-172-31-33-56.us-east-2.compute.internal host.docker.internal
Terminate the instance and created another T2.micro instance, but got same result.
Edit inbound rules to allow TCP:3306 from anywhere.
Can someone take a look? Any help appreciated.
It works on Ubuntu 20.04 after adding "172.17.0.1 host.docker.internal" to /etc/hosts file.
Make sure the docker engine version is 20.10-beta1 or newer.

Can't connect to Spring Boot app running on Docker locally

I stuck with the problem that can't open my REST Spring Boot app on localhost:8091 in browser.
Here is my docker-compose.xml (everything is deployed locally on Docker Desktop):
version: '3.3'
services:
postgres:
build:
context: services/postgres
dockerfile: Dockerfile.development
command: postgres
ports:
- "5432:5432"
environment:
- POSTGRESS_USER=postgres
- POSTGRESS_DB=postgres
- POSTGRESS_PASSWORD=qqq
- POSTGRES_HOST_AUTH_METHOD=trust
volumes:
- "db-data:/var/lib/postgresql/data"
app:
build:
context: services/app
dockerfile: Dockerfile.development
command: java -jar ./app.jar
environment:
- PORT=8091
network_mode: host
image: 'my-java-app'
ports:
- 8091:8091
depends_on:
- postgres
angular:
build:
context: services/angularfrontend
dockerfile: Dockerfile.development
image: 'my-angular-app'
ports:
- 80:80
volumes:
db-data:
Spring Boot App starts normally on 8091 and connects to the database, but then I can't make calls to it's API from my local machine ("connection refused").
Angular app opens normally (on localhost:80), but can't make calls to localhost:8091 Spring Boot app.
The call from angular service container to localhost:8091 fails, right?
Try to override in your angular frontend container the call to the backend
use app:8091 (this is how the backend service is called) instead of localhost:8091.
In the 'angular' container localhost doesn't translate to 'app' container.
You can't get from a container into a different container using localhost.
localhost inside a container will translate to the ip of that container.
Try to make in your angular application the call to the backend configurable, after that override that configuration in docker-compose using environment.
Also do that for the springboot app application.
I don't see in the environment that you override the call to the postgress.
Expose that configuration in application.properties and override in docker-compose, after that remove network_mode: host
If you really want to use network_mode: host, you don't need to specify <source>:<dest> because the app is listening on 8091 directly on the host network:
...
app:
build:
context: services/app
dockerfile: Dockerfile.development
command: java -jar ./app.jar
environment:
- PORT=8091
network_mode: host
image: 'my-java-app'
depends_on:
- postgres
...
If you want to run the java app like the other containers, simply remove this line from the compose file and the network mode will default to bridge:
network_mode: host

Make a request to a spring api running in a docker container from windows host

So, I searched around for an answer on this matter but either people don't address the issue or they say there's no problem doing this on their computer (mac or linux). It seems like this might be a windows problem.
I have a spring api running on a docker container (linux container). I use docker desktop on windows and I'm trying to make a request (in insomnia/postman/wtv) to that api.
If I run the api locally making the following request works perfectly:
http://localhost:8080/api/task/
This will list multiples task elements.
I've containerized this application like so:
Dockerfile
FROM openjdk:11.0.7
COPY ./target/spring-api-0.0.1-SNAPSHOT.jar /usr/app/
WORKDIR /usr/app
RUN sh -c 'touch spring-api-0.0.1-SNAPSHOT.jar'
ENTRYPOINT ["java", "-jar", "spring-api-0.0.1-SNAPSHOT.jar"]
docker-compose.yml
version: '3.8'
services:
api:
build: .
depends_on:
- mysql
environment:
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/test?createDatabaseIfNotExist=true
ports:
- "8080:80"
mysql:
image: mysql
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_USER=root
- MYSQL_PASSWORD=root
- MYSQL_DATABASE=test
If I do docker-compose up this works without issue:
The problem is, if I try to call the same endpoint as before from localhost I don't get any response.
Insomnia returns an error saying: Error: Server returned nothing (no headers, no data)
I've also tried connecting to the container's ip (got it from docker inspect) but no luck.
Ports are exposed in docker-compose.yml. What am I missing?
Thanks in advance.
Port mapping is incorrect.Spring boot application started at 8080 (from the image I see) inside container and it should be mapped to 8080 inside the container.
It should be like below:
ports:
- "8080:8080"

docker-compose: connection refused between containers, but service accessible from host

TL;DR: How do I have to change my below docker-compose.yml in order to allow one container to use a service of another over a custom (non-standard) port?
I have a pretty common setup: containers for a web app (Padrino [Ruby]), Postgres, Redis, and a queueing framework (Sidekiq). The web app comes with its custom Dockerfile, the remaining services come either from standard images (Postgres, Redis), or mount the data from the web app (Sidekiq). They are ties together via the following docker-compose.yml:
version: '2'
services:
web:
build: .
command: 'bundle exec puma -C config/puma.rb'
volumes:
- .:/myapp
ports:
- "9000:3000"
depends_on:
- postgres
- redis
sidekiq:
build: .
command: 'bundle exec sidekiq -C config/sidekiq.yml -r ./config/boot.rb'
volumes:
- .:/myapp
depends_on:
- postgres
- redis
postgres:
image: postgres:9.5
environment:
POSTGRES_USER: my-postgres-user
POSTGRES_PASSWORD: my-postgres-pass
ports:
- '9001:5432'
volumes:
- 'postgres:/var/lib/postgresql/data'
redis:
image: redis
ports:
- '9002:6379'
volumes:
- 'redis:/var/lib/redis/data'
volumes:
redis:
postgres:
One key point to notice here is that I am exposing the containers services on non-standard ports (9000-9002).
If I start the setup with docker-compose up, the Redis and Postgres containers come up fine, but the containers for the web app and Sidekiq fail since they can't connect to Redis at redis:9002. Remarkably enough, the same setup works if I use 6379 (the standard Redis port) instead of 9002.
docker ps also looks fine afaik:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9148566c2509 redis "docker-entrypoint.sh" Less than a second ago Up About a minute 0.0.0.0:9002->6379/tcp rubydockerpadrino_redis_1
e6d47321c939 postgres:9.5 "/docker-entrypoint.s" Less than a second ago Up About a minute 0.0.0.0:9001->5432/tcp rubydockerpadrino_postgres_1
What's even more confusing: I can access the Redis container from the host via redis-cli -h localhost -p 9002 -n 0, but the web app and Sidekiq containers fail to establish a connection.
I am using this docker version on MacOS:
Docker version 1.12.3, build 6b644ec, experimental
Any ideas what I am doing wrong? I'd appreciate any hint how to get my setup running.
When you bind ports like this '9002:6379' you're telling Docker to forward traffic from localhost:9002 -> redis:6379. That's why this works from your host machine:
redis-cli -h localhost -p 9002 -n 0
However, when containers talk to each other, they are all connected to the same network by default (the Docker bridge or docker0). By default, containers can communicate with each other freely on this network, without needing any ports opened. Within this network, your redis container is listening for traffic on it's usual port (6379), host isn't involved at all. That's why your container to container communication works on 6379.

Resources