Access to mysql container from other container - mysql

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/

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 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.

PhpStorm - How to connect to MySQL via Docker

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.

Docker communication without using legacy links

I'm trying to create a mini-demo with docker using mysql and phpmyadmin and i'm trying to make the two docker containers communicate with each other without using the --link flag since this has been flagged as "legacy" by docker (https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/#/connect-with-the-linking-system)
I managed to do this using docker-compose using the network section, but I want to implement the same scenario using normal dockerfiles and running the two containers in command prompt.
Here are the two dockerfiles I created:
Dockerfile for mysql
FROM mysql:5.7
ENV MYSQL_ROOT_PASSWORD=12345678
ENV MYSQL_DATABASE=mysql
ENV MYSQL_USER=user
ENV MYSQL_PASSWORD=12345678
Dockerfile for pma
FROM phpmyadmin/phpmyadmin:4.6
ENV PMA_HOST=mysql
ENV MYSQL_ROOT_PASSWORD=12345678
Docker images are created correctly using docker build and these are the commands that i use to run the two containers:
mysql:
docker run -d --name mysql sebastian/db-mysql
pma:
docker run -d -p 7777:80 --name pma sebastian/db-pma
When i try to connecto to Pma using username root and password 12345678 i get the following error:
mysqli_real_connect(): (HY000/2005): Unknown MySQL server host 'mysql' (-2)
I'm sure I'm missing something when spinning the two containers and I cannot fully understand how the two containers are suppose to communicate and/or how pma will find host mysql (the name i defined when running the mysql container)
Is docker suppose to allow communication between the two containers?
How do containers should find each other by using names and not ip addresses?
P.S. i'm using dockertoolbox on windows 10 (maybe that is the real problem :D )
The problem:
You are not specifying any networks in your docker run so you will use default bridge, Default bridge will not give you internal DNS but containers on that network can communicate via IP Addresses.
Follow these steps:
First create a user-defined network:
docker network create <yournetworkname>
Now run containers using the network we just created:
docker run -d --name mysql --network <yournetworkname> sebastian/db-mysql
docker run -d -p 7777:80 --name --network <yournetworkname> pma sebastian/db-pma
User defined networks provide connectivity by default and internal dns to the containers on the same network. For example you can ping mysql from pma by:
ping mysql

docker.io - Docker linking between application & database containers

I am trying to use my Scala-Akka application with my MySQL database on two separate Docker containers. I found out that Docker allows developers to link their application to their databases with the flag named --link. In my Dockerfiles in which I've used to create my images, I have add in EXPOSE 3306 8080 to it.
And this is how I run the containers:
docker run -d -p 3306:3306 --name mysql centos6mysql
docker run -d -p 8080:8080 --name scalaapp --link mysql:db centos6scala
After running the containers, I used docker ps and I am able to see the active containers. However, It seems like the application container is not using the database from the MySQL container. Anyone know what's wrong?
Linking in Docker allows network connections to be made between containers. Docker will define environmental variables to your linked containers for the URL, IP, port, and protocol. The names of these will be based on the name of your container. For instance:
DB_NAME=/web2/db
DB_PORT=tcp://172.17.0.5:5432
DB_PORT_5432_TCP=tcp://172.17.0.5:5432
DB_PORT_5432_TCP_PROTO=tcp
DB_PORT_5432_TCP_PORT=5432
DB_PORT_5432_TCP_ADDR=172.17.0.5
You can use these environmental variables to set up your Akka app container to connect to your DB container. However, you must manually configure the app container to do so. Docker will not make the connection for you automatically.
So, somewhere in your app, you will need to pass these values to your startup script, something that might look like:
./restcore --Ddb.default.db="jdbc:mysql//${DB_PORT_3306_TCP_ADDR}:${DB_PORT_3306_TCP_PORT"