PhpStorm - How to connect to MySQL via Docker - mysql

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.

Related

What is the best way to use existing external MySQL to Dockerized app?

In company we migrating some applications to Docker Container but apps has been connected to MySQL databse.
task which I stuck is the application is running on Docker and also the MySQL database which used by app I dockerized from officle image. But problem is the database is empty. i need to connect to already existing DB which is seperate server or migrate Data to newly created conternized Image. So I don't know which is best way and how to connect already exisitng db to dockerized app
I wanna ask what is the best way?
a) Dockerize MySQL from official image and migrate all data from host.(but data is very big to migrate) b) Connect App to the already existing database which is outside Docker container. c) Or any other way?
I tried to connect database which is outside Docker but not successfully
docker run -d --network=host \
-e "DB_DBNAME=database-1" \
-e "DB_PORT=3306" \
-e "DB_USER=admin" \
-e "MYSQL_ROOT_PASSWORD=pass" \
-e "DB_PASS=4815162342" \
-e "DB_HOST=database-1.amazonaws.com" \
--name somemysql2 mysql:latest
Any idea how to connect Docker app to the database which on another server and not in Docker container?
Thanks in advance for your help and support.
You have MySQL running in a Docker Container on a Host.
Different scenario's to connect to that MySQL Database:
From an App in another Container started in the same docker-compose.yml
If you started an App in the same docker-compose.yml and want to connect to the MySQL Database:
Use the Service as the Hostname because docker-compose has its own network and will translate the servicename to to right container
version: '3.9'
services:
mydb:
image: mysql:latest
volumes:
- "./.mysql-data/db:/var/lib/mysql"
restart: always
environment:
MYSQL_DATABASE: mysqldb
MYSQL_USER: root
MYSQL_PASSWORD: root
myapp:
....
In myapp you connect to MySQL with mysql://mydb:3306/....
No Ports section!! This is because MySQL itself publishes port 3306, so no Ports section needed in docker-compose.
From an App in another Container started in another Docker command
Suppose your App is started on the same Host but in another Docker command (or in another docker-compose.yml file)
Then you need to access the database via the Host published port. But there's a problem since you cannot access the host from within a Docker Container. (At least not in a stable way, so I leave out the hacky solutions you see here on StackOverflow)
Just create a (sub)domain and point it to your Host.
And make small change in your docker-compose.yml file: Add a Ports section:
ports:
- 3333:3306
The database can be found on mysql://subdomain:3333/.....
From an App running somewhere else on another Host.
This is the same as the previous solution:
Create subdomain
Publish the port
Connect to that subdomain
From Docker Container on Host to MySQL on another Server (not in Docker)
Again, same as before
Create subdomain
Publish the port on the Host
Connect to that subdomain
Solution with the subdomain need a ProxyServer?
In case your host also answers other requests from outside, you might need a ProxyServer (Nginx?) to route the 3333 traffic to port 3306 in the container.
And if you do have that ProxyServer, you don't need the Ports section anymore.
Answer to the question in the Problem Description
You want to connect to a MySQL database running on some AWS host.
That database is already running. It has a host, username, password.
Why are you starting a new Docker Container with MySQL Image?
Only thing you should start is that 'sampleapp' container with software connecting to the external MySQL.
I don't understand why you start a MySQL Container again if you already have an external one running on AWS.

How to connect docker container with host machine's localhost mysql database?

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.

How to connect to mysql docker container from flask application using sql-alchemy

I have a flask application. This application is running locally. I have pulled mysql:5.7 and it is running. I want to create a database inside the mysql:5.7 container from the flask application and use that. I am using sql_alchemy.
I have given the uri as
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:root#172.17.0.2:4000/document_generator'
where root and root are mysql username and password respectively. 172.17.0.2 is the ip address of the mysql container. I have run the container using
docker run -p 4000:4000 -e MY_SQL_ROOT_PASSWORD=root mysql:5.7
I have exposed the port 4000. But, when i get inisde the conatiner and try
show global variables like 'port';
it gave 3306 as the port.
I tried using both the ports in the SQL_ALCHEMY_URI, but none of them were able to create the database.I also tried changing mysql:// to mysql+pymsql://. Even that dint work.
I have written the table creation code inside models.py
class Users(db.Model):
__tablename__ = 'users'
username = db.Column(db.String(128), nullable=True)
password = db.Column(db.String(256), nullable=False)
private_id = db.Column(db.String(128), primary_key=True)
I want the database to be created in the mysql container when i run my flask application. I have no idea about docker-compose. Any help would be of great help. Thanks in advance.
Your docker run command specificities the port to be published as 4000:4000.
The left side of the : is 4000 which is the port on your local machine, and that's fine.
But the right side of the : which is also 4000 is the port inside the container where is running MySQL. The default port of MySQL is 3306, not 4000, so you're trying to reach MySQL on the wrong port.
To fix that:
Stop the docker container
# Show all the running containers. The last column should be the container name.
$ docker ps
# Stop and remove the container
$ docker rm -f <container name>
Re-create the container with the right port
$ docker run -p 4000:3306 -e MY_SQL_ROOT_PASSWORD=root mysql:5.7
Now it should work.
Bonus
Docker exposes the containers also on the localhost. You can also reach the database on localhost:4000.
Publishing port will not change the PORT in MySQL schema, if you want to connect with MySQL container using port 4000 you just need to map 4000 with 3306.
docker run -p 4000:3306 -e MY_SQL_ROOT_PASSWORD=root mysql:5.7
Also will suggest using docker network instead of IP of the container, as IP change frequently.
But still if you want to start MySQL on port 4000 you can try something like
docker run -it -p 4000:4000 -e MY_SQL_ROOT_PASSWORD=root mysql:5.7 --port=4000
And then if you query like
show global variables like 'port';
You will get 4000.

Can't connect to Windows 10 Docker mysql

Win 10
Composer version 1.4.1 2017-03-10 09:29:45
PHP 7
npm/Node
Docker CE
Apache 2.4
Powershell
git BASH shell
drush (installed via composer)
Noob Composer/Docker skills
I have a docker config yml specifying how mysql service can start:
version: "2"
services:
mysql:
image: mysql:5.6
ports:
- 3306:3306
volumes:
- /data/nbif_mysql:/var/lib/mysql
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
And when I call
#!/bin/bash
docker-compose up -d mysql
I see that the container is running:
PS C:\dev\appname> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f1a0ecab8af6 mysql:5.6 "docker-entrypoint..." 2 hours ago Up 5 seconds 0.0.0.0:3306->3306/tcp appname_mysql_1
But, notice that the reported IP is 0.0.0.0:3306->3306/tcp
So when I try to connect with the expected IP, it fails:
ERROR 2003 (HY000): Can't connect to MySQL server on '172.17.0.1' (10060)
How to I tell docker-compose to use that expected IP for docker?
Is this a setup issue, or some config tweak I need to do?
When you bind a port to your host, you have to use localhost instead of the container's IP address, because you're not assigning any local IP address.
Every container always runs in a isolated network (bridge), the container in your compose file will be able to find the others by their hostname, but inside of those containers, they are isolated from the local network so that's why you can't reach them.
In your compose file you only have a mysql container and you're binding that port in your host, so the only way to reach that container is by using localhost:3306
Remember, when you run a docker container it isn't like a server with an IP in your host network, it's more like a virtual machine with an isolated network configuration.
Take a look on the docker-compose docs in this specific topic:
https://docs.docker.com/compose/networking
UPDATE:
The link that finally answered the question was:
https://docs.docker.com/engine/userguide/networking/default_network/custom-docker0/

Access to mysql container from other container

I have setup docker container with mysql that expose 3306.
I've specified database user, database password and create a test db and give the privileges to new user.
In another container i want to accesso to this db.
So i set up new container with a simply php script that create new table in this db.
I know that mysql container's ip is 172.17.0.2 so :
$mysqli = new mysqli("172.17.0.2", "mattia", "prova", "prova");
Than using mysqli i create new table and all works fine.
But i think that connect to container using his ip address is not good.
Is there another way to specify db host? I tryed with the hostname of the mysql container but it doens't work.
The --link flag is considered a legacy feature, you should use user-defined networks.
You can run both containers on the same network:
docker run -d --name php_container --network my_network my_php_image
docker run -d --name mysql_container --network my_network my_mysql_image
Every container on that network will be able to communicate with each other using the container name as hostname.
You need to link your docker containers together with --link flag in docker run command or using link feature in docker-compose. For instance:
docker run -d -name app-container-name --link mysql-container-name app-image-name
In this way docker will add the IP address of the mysql container into /etc/hosts file of your application container.
For a complete document refer to:
MySQL Docker Containers: Understanding the basics
In your docker-compose.yml file add a link property to your webserver service:
https://docs.docker.com/compose/networking/#links
Then in your query string, the host parameter's value is your database service name:
$mysqli = new mysqli("database", "mattia", "prova", "prova");
If you are using docker-compose, than the database will be accessible under the service name.
version: "3.9"
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
ports:
- "8001:5432"
Then the database is accessible using: postgres://db:5432.
Here the service name is at the same time the hostname in the internal network.
Quote from docker docs:
When you run docker-compose up, the following happens:
A network called myapp_default is created.
A container is created using web’s configuration. It joins the network myapp_default under the name web.
A container is created using db’s configuration. It joins the network myapp_default under the name db.
Source:
https://docs.docker.com/compose/networking/