I have a war file that uses the MySQL database in the backend.
I have deployed my war file in a docker container and I am able to ping this from my browser.
I want to connect my app with the MySQL database. This database exists on my host machine's localhost:3306
As I am unable to connect this from inside container's localhost, what I tried is,
I run a command docker inspect --format '{{ .NetworkSettings.IPAddress }}' 213be777a837
This command gave me an IP address 172.17.0.2. I went to MySQL server options and put this IP address in the bind field and restarted the server. After that, I have updated my projects database connection string with 172.17.0.2:3306
But it is not working. Could anyone please tell what I am missing?
I have also tried adding a new DB user with root#% and then run command allow all permission to 'root#%' but nothing worked.
Follow the steps:-
docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 dockernet
docker run -p 8082:8080 --network dockernet -d 6ab907c973d2
in your project set connection string : jdbc:mysql://host.docker.internal:3306/....
And then deploy.
tl;dr: Use 172.17.0.1:3306 if you're on Linux.
Longer description:
As I understand what you need to do is to connect from your Docker container to a host port. But what you have done is to try to bind the host process (MySQL) to the container networking interface. Not sure what the implications of a host process trying to bind to another host process network namespace, but IIUC your MySQL process should not be able to bind to that address.
When you start MySQL with default settings that bind it to 0.0.0.0 it's available for Docker containers through the Docker virtual bridge. Therefore, what you should do is to route your requests from the WAR process to the host process through that virtual bridge (if this is the networking mode you're using. If you have not changed any Docker networking settings, it should be). This is done by specifying the bridge gateway address as the MySQL address and the port it's started with.
You can get the bridge IP address by checking your network interfaces. When Docker is installed, it configures the virtual bridge by default, and that should show up as docker0 if you're on Linux. The IP address for this will most probably be 172.17.0.1. So your MySQL address from the container's point of view is jdbc:mysql://172.17.0.1:3306/....
1 - https://docs.docker.com/network/
2 - https://docs.docker.com/network/bridge/
From your question, I am assuming you both your war file and MySQL is deployed locally, and you want to connect them. One way to allow both containers that are locally deployed to talk to each other is by:
Create your own network docker network create <network-name>
Then when you run your war file and MySQL, deploy both of them using the --network. E.g.
War File: docker run --name war-file --network <network-name> <war file image>
MySQL: docker run --name mysql --network <network-name> <MySQL image>
After that, if you should be able to connect to your MySQL using mysql:3306 from inside your war file docker container, since they are both on the same custom network.
If you want to read up more about this, can take a look at docker documentation on network. (https://docs.docker.com/network/bridge/).
Your setup is fine. You just need to do this one change.
While running the application container (the one in which you are deploying your war file), you need to add following argument in its docker run command.
--net=host
Example:
docker run -itd -p 8082:8080 --net=host --name myapp myimage
With this change, you need not to change connection string as well. localhost:3306 would work fine. And you will be able to set up a connection with MySQL.
Related
I am using kubernetes (by windows 10 - docker desktop).
I am using mysql, that is running by helm 3 (loaded from bitnami repository).
I am creating another application.
For now, I am testing on docker (not in kubernetes yet).
Everything is fine, but when trying to connect the database from my project
(BTW - Project works fine, but not when running on docker).
Something like:
docker run --name test-docker --rm my-image:tag --db "root:12345#tcp(127.0.0.1:3306)/test"
(db is a parameter to to connect to db).
I get the message:
2022-02-21T12:18:17.205Z FATAL failed to open db: could not setup schema: cannot create jobs table: dial tcp 127.0.0.1:3306: connect: connection refused
I have investigate a little, and find that the problem may be because the dockers running need to run on the same network.
(Nonetheless, they are actually dockers, when one is running by helm tool for K8S).
this is on:
kubernetes networking
When I run:
nsenter -t your-container-pid -n ip addr
the pid is not directory, so I get the message:
/proc/<pid>/ns/net - No such file or directory
How can I eventually run my project that can use the mysql (running in dockers on K8S)?
Thanks.
Docker containers are isolated from other containers and the external network by default. There are several options to establish connection between Docker containers:
Docker sets up a default bridge network automatically, through which the communication is possible between containers and between containers and the host machine. Both your containers should be on the bridge network - for container with your project to connect to your DB container by referring to it's name. More details on this approach and how it can be set up is here.
You can also create user-defined bridge network - basically, your own custom bridge network - and attach your Docker containers to it. In this way, both containers won't be connected to the default bridge network at all. Example of this approach is described in details here.
First, user-defined network should be created:
docker network create <network-name>
List your newly created network and check with inspect command its IP address and that no containers are connected to it:
docker network ls
docker network inspect <network-name>
You can either connect your containers on their start with --network flag:
docker run -dit --name <container-name1> --network <network-name>
docker run -dit --name <container-name2> --network <network-name>
Or attach running containers by their name or by their ID to your newly created network by docker network connect - more options are listed here:
docker network connect <network-name> <container-name1>
docker network connect <network-name> <container-name2>
To verify that your containers are connected to the network, check again the docker network inspect command.
Once connected in network, containers can communicate with each other, and you can connect to them using another container’s IP address or name.
EDIT: As suggested by #Eitan, when referring to the network instead of a changing IP address in root:12345#tcp(127.0.0.1:3306)/test, special DNS name host.docker.internal can be used - it resolves to the internal IP address used by the host.
This might sound repeated question but it is not and this is a crazy bug I feel, however, let me quickly explain my setup:
A simple Spring bootstrap application that runs pretty well on my local and JDBC connection string in application.properites file is as follows.
spring.datasource.url=jdbc:mysql://minesql:3306/datamachine?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=****
The docker running instances are:
I copied (with the help of docker cp command) the war file to alpine (unix container) and running it in interactive mode to test and it is throwing exception as it is unable to ping the mysql server. I am certain that the database configurations are fine and clueless why the springboot app is failing to connect to mysql container instance. Note, the mysql container does have "datamachine" database created manually.
This is the error reported:
Please help me understand what I am missing here or what is going wrong.
Just in-case if you wish to know how I started these containers.
For mysql:
docker run -d --name minesql -e MYSQL_ROOT_PASSWORD=**** -p 3306:3306 mysql
Running Java app from the alpine container and this is how I am starting the alpine,
docker run -it --name unix alpine
The interactive mode present me the bash prompt to run the spring-boot war file. (..and running the war file after installing the java 8 in alpine)
You have two docker containers which are running and connected via default bridge network. From docker bridge documentation
Containers on the default bridge network can only access each other by
IP addresses, unless you use the --link option, which is considered
legacy. On a user-defined bridge network, containers can resolve each
other by name or alias.
If you need the second container to be able to resolve the name minesql from inside, you need to create a user-defined network bridge and connect the docker container containers to that.
Create a new network using
docker network create my-net
And add your containers as specified here
Other alternative is to use docker-compose and avoid manual creation of bridge networks for name resolution. For production environment, that would be ideal.
I am working with PhpStorm 2018.3.4, Docker, MySQL and Ubuntu.
I tried unsuccessfully to configure MySQL with the Docker container network_mysql.
First, I have tried this configuration :
It gave me this error :
Then, I tried this :
This one gave me this other error.
Am I missing something? Is there another place where I must configure something?
docker ps output :
Here docker network ls :
For the command docker inspect network_mysql, here is a link to the description :
https://pastebin.com/9LmeAkc8
Here is a docker-compose.yml configuration :
https://pastebin.com/DB4Eye4y
I tried to put - "3306:3306" in addition to the wex_server_proxy section with no avail.
The file to modify was this one :
https://pastebin.com/TPBQNCDZ
I added the ports section, opening the 3306 port :) And then, it works.
Solution
I notice that you are not mapping the mysql container port out. If you did, you would see this from the docker ps command:
... 0.0.0.0:3306->3306/tcp network_mysql
The container network_mysql is attached to a bridge type network called tmp_wex_net. This means that the container is not accesible from the host, by it's container name.
I appears that you are using a docker-compose.yml definition for the stack. In order to be able to access the container from the host, you need to use the ports section of your compose definition for this container:
serivces:
mysql:
...
ports:
- "3306:3306"
...
If you are starting it with docker run, then you can acomplish the same thing with:
docker run -p 3306:3306 --name network_mysql --network="tmp_wex_net" -d mysql
And then use localhost in the hostname of your connection settings in PHPStorm. Like this:
Host: localhost
Port: 3306
Database: network
The problem
The reason that you are not able to connect, is that the host name network_mysql that you specify in the connection settings, does not resolve to any host that your machines knows of.
The container name of a docker container, is not a DNS name that the docker host can resolve.
If you have not specified any network for your mysql container, then it is connected to the default bridge network. And if you have created a new network, without specifying the type - it will also default to the bridge driver.
In order to access the container from the host, you need to either:
Connect the container to the host network
Or from a container on a bridge network, map the port to the host like suggested in the solution above. You can then address the specifically mapped port on that container with localhost:<portnum> from the host machine.
For everyone who has setup mysql manually in a docker image:
chances are you must configure mysql to accept incoming connections also from the network interface which docker creates/uses to communicate with the host (along with port forwarding).
in my case, i added the following to /etc/mysql/my.cnf to the end of the file:
[mysqld]
bind-address = 0.0.0.0
With that mysql listens on all network interfaces.
My solution:
I forwarded ports from localhost to remote: ssh -R 3306:localhost:3306 root#remote_host_ip and the connection was successful.
A bridge network has been created in docker using the following:
docker network create blognetwork
And a container has been created in that network with the following:
docker run --name=blogdb --network=blognetwork -p 3306:3306 -e --bind-address=0.0.0.0 -e=MYSQL_ROOT_PASSWORD=mypassword -detach mysql
How do I access the ip address of the new container, within the "blognetwork", from a windows host?
How do I get the ip address of the form X.X.X.X, on its own? I know I can use the following to get a large json output with this data in it:
docker network inspect blognetwork
You can get directly the ip by using docker inspect and a proper format:
docker inspect containerId --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}'
More info in the Docker documentation.
You can get directly the IP address by using docker inspect. Docker inspect provides detailed information on constructs controlled by Docker.
Modern Docker client syntax is:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id
Old Docker client syntax is:
docker inspect --format '{{ .NetworkSettings.IPAddress }}' container_name_or_id
These commands will return the Docker container's IP address.
If you are on Windows, use double quotes " instead of single quotes ' around the curly braces.
For more information Docker inspect documentation.
Here is the command to get container information along with container IP.
docker inspect 'ContainerID'
Since you ran
docker run -p 3306:3306 ...
you should access the service via port 3306 using your host's DNS name or IP address.
In the very specific case where you're at a shell prompt or browser URL entry on the machine where you ran docker run, assuming you're not using Docker Machine or Docker Toolbox, in this case and in this case only, you can use localhost:3306 to access the container. Never ever use localhost for anything else around Docker unless you're totally clear what it means. (If you ever start writing a question that uses the words "...the localhost of..." then localhost isn't what you want.)
If you are trying to reach this container from another container, since you ran
docker run --name=blogdb --network=blognetwork ...
you can use the name blogdb as a host name, and Docker provides an internal DNS service that can resolve it to something that will reach the container.
You never want the Docker-internal IP address, and should never run docker inspect to try to find it. The two biggest problems with it are that it's unreachable from off-host and that it changes when the container is deleted and recreated.
HI I have my web app running on my local machine and connected to Mysql workbench, I am now trying to dockerize the webapp. I can't seem to get it to connect to the DB on my local dev machine (I am running Docker Desktop for Windows), can anyone tell me how I would go about this? Here is what I have so far.
`docker run -it -e "CATALINA_OPTS=-Dspring.profiles.active=dev -DPARAM1=DEV" -p 8080:8080 -p 8005:8005 -p 8009:8009 -p 3306:3306 --add-host=docker:192.168.1.7 -v C:\myapp\trunk\target\myapp.war:/usr/local/tomcat/webapps/myapp.war --name waitapp tomcat:8.0.38-jre8`
after a few second, I run docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2a1764dd9640 tomcat:8.0.38-jre8 "catalina.sh run" 2 minutes ago Up 2 minutes 0.0.0.0:3306->3306/tcp, 0.0.0.0:8005->8005/tcp, 0.0.0.0:8009->8009/tcp, 0.0.0.0:8080->8080/tcp waitapp
The container seems to be running, but I get a 404 Not found when I try the rest request, this is the same as I do when running from inside spring tool suite using built in tomcat server.
NOTE
I don't want to run a separate mysql container and link the two over a network, I just want to try get my newly created docker app to connect to my local DB MySQL.
As mentioned on this post, you can try 2 things:
Add gateway and use it from containers, like
docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 dockernet
In addition to your app container, run proxy (ngnix?) container, which will rout the calls to DB when required
This answer also show how can you obtain the host IP inside the docker container.