Trouble communicating between two docker containers - java

I’m new to docker and I’m trying to connect my spring boot app running into my boot-example docker container to a mysql server running into my mymysql docker container on port 6603, both running on the same phisical machine.
The fact is: if I connect my spring-boot app to my mymysql docker container in order to communicate with the database, I get no errors and everything works fine.
When I move my spring boot application into my boot-example container and try to communicate (through Hibernate) to my mymysql container, then I get this error:
2018-02-05 09:58:38.912 ERROR 1 --- [ main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool.
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_111]
My spring boot application.properties are:
server.port=8083
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.url=jdbc:mysql://localhost:6603/mydockerdb
spring.datasource.username=root
spring.datasource.password=mypassword
It works fine until my spring boot app runs in a docker container on port 8082, (after the docker image is correctly built):
docker run -it -p 8082:8083 boot-example

You cannot use localhost inside the container, it's the container itself. Hence, you will always get the connection refused error.
You can do below things -
Add your host machine IP in application.properties file of your spring boot application. (Not recommended since it breaks docker portability logic)
In case you want to use localhost, use --net=host while starting the container. (Not recommended for Production since no logical network layer exists)
Use --links for container communication with a DNS name. (deprecated/legacy)
Create a compose file & call your DB from spring boot app with the service name since they will be in same network & highly integrated with each other. (Recommended)
PS - Whenever you need to integrate multiple containers together, always go for docker-compose version 3+. Use docker run|build to understand the fundamentals & performing dry/test runs.

As #vivekyad4v suggested - the easiest way to achieve your desire, is to use docker-compose which has better container communication integration.
Docker-compose is a tool for managing single or multiple docker container/s. It uses single configuration file called docker-compose.yml.
For better information about docker-compose, please take a look at documentation and compose file reference
In my experience, it is good practice to follow SRP (single responsibility principle), thus - creating one container for your database and one for your application. Both of them are communicating using network you specify in your configuration.
Following example of docker-compose.yml might help you:
version: '2'
networks:
# your network name
somename:
driver: bridge
services:
# PHP server
php:
image: dalten/php5.6-apache
ports:
- 80:80
volumes:
- .application_path:/some/application/path
# your container network name defined at the beggining
networks:
- somename
# Mysql server for backend
mysql:
image: dalten/mysql:dev
ports:
- 3306:3306
# The /var/lib/mysql volume MUST be specified to achieve data persistence over container restart
volumes:
- ./mysql_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: backend
# your container network name defined at the beggining
networks:
- somename
Note: Communication between containers inside network can be achieved by calling the service name from inside container.
The connection parameters to MySQL container from PHP, would in this example be:
hostname: mysql
port: 3306
database: backend
user: root
password: root

As per above suggestion, Docker-compose is a way but if you don't want to go with compose/swarm mode.
Simply create your own network using docker network create myNet
Deploy your containers listening on a created network --network myNet
Change your spring.datasource.url to jdbc:mysql://mymysql:6603/mydockerdb
By using DNS resolution of docker demon, containers can discover each other and hence can communicate.
[DNS is not supported by default bridge. A user-defined network using bridge does.]
For more information: https://docs.docker.com/engine/userguide/networking/

Related

communicate with a container created with docker-compose

i have macOS 11.5, docker desktop 4.10, microservices with spring boot.
I use docker-compose to allow me to start my microservices.
A portion of docker-compose:
authentication-server:
build: ./authentication-server
network_mode: "host"
image: authentication-server: 0.0.9
hostname: authentication-srv
ports:
- "4445:4445"
basically I need to communicate with the container, interrogating it from my pc using Postman, then a REST request.
Despite the nerwork_mode: "host" when I try to ping localhost: 4445 it tells me
"ping: cannot resolve localhost: 4445: Unknown host".
As well as trying the various container names:
"ping: cannot resolve authentication-srv: 4445: Unknown host"
"ping: cannot resolve authentication-server: 4445: Unknown host"
So my need is to communicate with a container created with docker-compose on my local pc. How can I solve? thank you

Create queues in IBM MQ (docker compose )

I'm developing a Spring Boot app which is using IBM MQ. I want all of that to be configured in the docker compose. But the problem is that in the app there are used custom queues that were created from the UI in the browser, example of application.yml file:
...
ibm:
mq:
queues:
first: QUEUE1
second: QUEUE2
How do I create these queues on the startup now when I'm I want to run it from the docker compose file? When I was running ibm mq manually I was using command like this:
docker run --env LICENSE=accept --env MQ_QMGR_NAME=QM1 --publish 1414:1414 --publish 9443:9443 --detach ibmcom/mq:latest
And now I'm almost doing the same but in the docker-compose.yml file:
...
ibm-mq:
image: 'ibmcom/mq:latest'
container_name: ibm-mq
ports:
- "1414:1414"
- "9443:9443"
environment:
- LICENSE = accept
- MQ_QMGR_NAME = QM1
Is there any environment variables to create custom queues or how do I do that? I didn't find any solution to this.
Based on this information: Customizing the queue manager configuration, you can create a MQSC file named 20-config.mqsc with some config options that will be run when your queue manager is created. Just put it into the /etc/mqm directory on the image.
So, create your 20-config.mqsc file like this:
DEFINE QLOCAL(QUEUE1) REPLACE
DEFINE QLOCAL(QUEUE2) REPLACE
And map it to your docker-compose.yml as a volume like this:
ibmmq:
image: ibmcom/mq
ports:
- "1414:1414"
- "9443:9443"
environment:
- LICENSE=accept
- MQ_QMGR_NAME=QM1
volumes:
- <your 20-config.mqsc file path>:/etc/mqm/20-config.mqsc
It works for me
Chapter Customizing the queue manager configuration describes the options:
You can customize the configuration in several ways:
For getting started, you can use the default developer configuration, which is available out-of-the-box for the MQ Advanced for Developers image
By creating your own image and adding your own MQSC file into the /etc/mqm directory on the image. This file will be run when your queue manager is created.
By using remote MQ administration, via an MQ command server, the MQ HTTP APIs, or using a tool such as the MQ web console or MQ Explorer.

proper usage of MySQL docker container while integrating with java application

Currently I am trying to implement some eCommerce functionality in java. And I would like to pull data from MySQL and utilize the same. So for this purpose I wanted to use MySQL docker container for the first time. And in my Linux server(host) I have installed docker and created a custom MySQL container with Image. so here the question is how to use this container in my local computer. And is this the way we suppose to access MySQL from local ?? or we create a different container for our local server by installing docker from the image? And how to access this container from host server (I mean the endpoint). Could someone please elaborate the clear use case of MySQL docker container. if you have any questions for my query please ask so that I will reply in comments.
in my opinion:
first I have used MySQL official image and I have created a docker-compose.YAML file for creating a new container.
following commands is an example for you.
just pay attention to create a network first and put your MySQL and java containers at the same network.
docker network create mysql-network
then create a yaml file and put these commands:
mysql:
image: mysql:8.0
container_name: mysql
restart: always
networks:
#- mysql_network
- mysql_newtwork
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: 123456789
MYSQL_DATABASE: database
MYSQL_USER: user_db
MYSQL_PASSWORD: 123456
ports:
- 3306:3306
volumes:
- /home/mysql_backup/storage/mysql-data/dev:/var/lib/mysql

communication between docker containers (keycloak and spring)

So I have created a java spring boot application which uses Keycloak for authenticating its users.
When I run keycloak from docker-compose I can sucesfully authenticate when running my application as a standalone jar file or when debugging. But when I put my spring boot application as a docker containers inside docker-compose. I cannot authenticate users anymore.
my error log from spring boot docker container:
springBootApp | 2019-12-19 13:16:41.498 ERROR 1 --- [nio-8081-exec-2] o.k.a.rotation.JWKPublicKeyLocator : Error when sending request to retrieve realm keys
springBootApp |
springBootApp | org.keycloak.adapters.HttpClientAdapterException: IO error
I though that the problem is with network. but all containers are running in the same virtual network. They are also also in same docker-compose file.
this is my keycloak part:
keycloak:
image: jboss/keycloak
ports:
- 18080:8080
volumes:
- ../keycloak:/opt/jboss/keycloak/imports
command:
- "-b 0.0.0.0 -Dkeycloak.import=/opt/jboss/keycloak/imports/realm-export.json"
environment:
- KEYCLOAK_USER=admin
- KEYCLOAK_PASSWORD=admin
my spring boot app
mySpringBootApp:
image: mySpringBootApp:master-1
environment:
- SPRING_PROFILES_ACTIVE=developmentTest
depends_on:
- jaeger
- keycloak
- db
ports:
- "8081:8081"
When I try to use
curl localhost:18080 from my host. I get the response.
when I try to use curl from springBootApp docker I get connection refused. So I assume that even though they are in the same network they don't see each other.
You have to keep in mind that your docker container is isolated from the host it is running on. localhost for your computer is different then localhost from inside the docker container.
You are using docker-compose and both services are in the same docker-compose.yaml configuration this means you can use the service name of a service to reach it from within another service that is in the same docker-compose file.
In your case the service you want to access is called keycloak and you have mapped its ports as 18080:8080 meaning that from your computer localhost 18080 accesses the port 8080 of this particular container.
In order to access this container (or service in a docker-compose context) you need to replace localhost by the name of your service.
In your case to curl the keycloak container from mySprngBootApp container you need to replace lcalhost by the name of the service so long story short: curl keycloak:18080
I would define network for your services in docker compose, like:
services:
app:
image: some-image
networks:
- my-network-name
networks:
my-network-name:
name: my-global-net
And you can be sure, that services are in the same network and speak via service's name with each other.

Cannot connect to remote MSSQL database from stacked docker container

I have a problem with connecting to existing remote MSSQL database from inside of a docker container running in stack.
My application consists of three modules (backend, frontend and haproxy)
Backend module is written in Java (SpringBoot app) and it's also the one that needs to connect do remote MSSQL database (by remote I mean placed on different sever, separate of docker part).
I have the following docker compose file:
I start the stack by using following command:
docker stack deploy -c docker-compose.yml myapp
The result is, all containers are up and running, but spring app reports that connection to DB is timed out:
Server seems to be configured properly, I am able to access the host from container through telnet.
When running independently (even from docker container) backend app is able to connect to database with no problems, while stacked with docker-compose however it's unable to connect to the very same db.
I've also tried to provide db server IP instead of host name - no success.
Maybe setting up networks section in docker compose would do the trick?
UPDATE
Another thing you can do is to use host.docker.internal instead of the IP address of the database. This ONLY works on docker for windows or docker for mac.
Source: I want to connect from a container to a service on the host
OLD, only works when not in swarm mode
You need to specify that docker should use the same network as the host, you can do this in the following way:
version: '3'
services:
web-app:
build:
dockerfile: web-app/something
ports:
- 8080:8080
network_mode: "host"
Reference: Use host networking
It seems that the issue was caused by networks overlapping.
Adding network configured as show below, allowed either to connect to my remote database and keep my endpoints hidden:
networks:
backend:
ipam:
driver: default
config:
- subnet: 192.168.40.0/26

Categories

Resources