Accessing to mysql from host to container in cli - mysql

I created my container like this:
$ docker run -d -p 33060:3306 myimage
Then I try connect from host to mysql server in container:
$ mysql -uroot -proot -P 33060
I got this error:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
It odd because in Navicat only I changed the port and work fine:
But If I have the IP of the container:
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' mycontainer
172.17.0.55
Then I can connect to mysql server successfully:
$ mysql -uroot -proot -h 172.17.0.55
But it is a tedious task have to check the ip each time I create a new container to connect to mysql. There any settings I can do to make this task simpler?

This is not a Docker issue. By default the mysql command-line client will connect to a local (Unix) socket instead of a network one, even if you specify -P.
This behavior is described in the documentation:
On Unix, MySQL programs treat the host name localhost specially, in a way that is likely different from what you expect compared to other network-based programs. For connections to localhost, MySQL programs attempt to connect to the local server by using a Unix socket file. This occurs even if a --port or -P option is given
You have to pass the -hlocalhost option, or you can set your connection defaults in /etc/mysql/my.cnf

Related

How to connect to ProxySQL with default config on Docker

I installed docker, got the most popular box with proxySQL.
docker run -d -p 6032:6032 --name proxysql prima/proxysql:latest
then I tried to connect to it from my local mysql like so:
mysql -u admin -padmin -h 127.0.0.1 -P6032
and I'm getting this error:
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0 "Internal error/check (Not system error)"
I tried this trick with twindb/proxysql:latest and prima/proxysql:latest docker images and the result was the same :(
You cannot connect to proxysql from outside the container in default config. bash into the proxysql container and then execute
mysql -u admin -p<password-here> -h 127.0.0.1 -P 6032 --prompt='proxysql>'
default password will be the admin
You need to map 6033 instead of 6032
docker run -d 6033:6033 --name proxysql prima/proxysql:latest
And then run below
mysql -u admin -padmin -h 127.0.0.1 -P6033
Inside the container mysql listens on 127.0.0.1:6032 and for outside connections it listens on 0.0.0.0:6033. So you need to use 6033 for connections from outside the container

Accessing a Docker MySQL server from the host machine, without needing the container's IP address

I'm writing setup instructions for an application needing a MySQL database, and I'd like it to be easy even for people that don't have a MySQL installation.
Therefore, I'd like to run the MySQL server in a container:
docker run -p 3306:3306 \
--name mysql \
-e MYSQL_ROOT_PASSWORD=test \
-e MYSQL_DATABASE=my_db \
-d mysql
And to be able to connect to it this way:
mysql -u root -ptest -D my_db
Which doesn't work because the MySQL server only listens locally on the container.
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
So I see three options, none of which fitting my needs:
1) Using the container IP everytime
mysql -u root -ptest -D my_db -h 172.17.0.4
Annoying, the IP will often change and I don't want people to have to update their configuration this much.
2) Changing the configuration of MySQL inside the container
Requires to run a docker exec ... each time the container is run, so it's annoying as well.
3) Making a custom image where the configuration suits my needs
Seems a bit overkill, I'm pretty sure there is a better solution.
Thoughts?
When the mysql client is invoked as you did:
mysql -u root -ptest -D my_db
(i.e. without the hostname) or with localhost as hostname it tries to connect to the local server using Unix pipes. A pipe is a special file type and the client communicate with the server through it.
Your MySQL server is not local, it runs on a separate machine. You cannot connect to it using pipes.
As you already noticed, it works if you use the IP address of the container as argument for the -h command line option of mysql.
You also map the port 3306 of the container to port 3306 of the host machine. This means any TCP connection to port 3306 of the local machine goes through this mapping to the port 3306 of the container, where the MySQL server is listening.
Combining the two above, all you have to do is to put 127.0.0.1 as host name in the mysql command line:
mysql -u root -ptest -D my_db -h 127.0.0.1

Cannot connect to MySQL server inside Docker

First I run mysql image:
docker run -e MYSQL_ROOT_PASSWORD=password -d -p 127.0.0.1:3308:3306 mysql
Then I use container bash:
docker exec -it my_container_name bash
In Bash I can successfully connect to MySQL server via command:
mysql -uroot -ppassword
But when I try to connect to MySQL container from Windows cmd:
mysql -uroot -ppassword -h127.0.0.1 -P3308
ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1' (10061)
If I connect to 192.168.99.100 instead (this ip is returned by docker-machine ip), then the result is the same.
The question is: How do I correctly expose my MySQL port inside Docker to outside Windows?
The error is in your port mapping in the original docker run command, you just need to provide the ports, not the IP address:
docker run -e MYSQL_ROOT_PASSWORD=password -d -p 3308:3306 mysql
You can run docker ps -a to check for the port mapping in the running containers.
You should now be able to connect to MySQL using
mysql -uroot -ppassword -h192.168.99.100 -P3308
First, check netstat -an to make sure the port is open in Windows. If it is, also check the Windows firewall to make sure nothing is blocking connections to the port.
Most of my Docker experience is in CoreOS, so I'm not exactly sure how Windows handles routing traffic into the container. In CoreOS, it uses a proxy. If there is a proxy in Windows, make sure nothing is interfering with it.
Changing the port in which I was running the image worked.
I checked if this port was used by something else, but it was not used. so I just -desperately- run a new container in a different port '3309'. and it worked fine!
Make sure you have entered the port with -P.

How can I access my docker maria db?

My main question is that after I have created a docker container for my mariadb with the command docker run --name db -e MYSQL_ROOT_PASSWORD=test -d -p 3306:3306 mariadb how can I access the sql db?
Somewhere I have seen a solution using a temporal (after exit the container is deleted) container, but cannot find it anymore.
I am searching for a command like: sudo docker exec -it [other flags] [command] db.
Just mysql-client, no extra docker container
Install the mysql client on your host,
apt-get install mysql-client
then use the following command to access your database container.
mysql -u<user> -p<pass> -h $(docker inspect --format '{{ .NetworkSettings.IPAddress }}' <db-container>)
The command will automatically get the IP of your docker container.
Make sure to replace <user>, <pass> and <db-container> with your respective values. In your case:
mysql -uroot -ptest -h $(docker inspect --format '{{ .NetworkSettings.IPAddress }}' db)
Your command lets mariadb run at the standard port 3306. If not, you have to tell the mysql command the new port.
from Official Mariadb website:
Connecting to MariaDB from Outside the Container
If we try to connect to the MariaDB server on localhost, the client will bypass networking and attempt to connect to the server using a socket file in the local filesystem. However, this doesn't work when MariaDB is running inside a container because the server's filesystem is isolated from the host. The client can't access the socket file which is inside the container, so it fails to connect.
Therefore connections to the MariaDB server must be made using TCP, even when the client is running on the same machine as the server container.
Most MariaDB images, including the official one, have external TCP connections disabled using the bind-address option in their #my.cnf# file. The docker image used in this guide is based on Ubuntu, so the file is located at /etc/mysql/my.cnf.
To use MariaDB we will need to edit the configuration file to change the appropriate option, and then restart the container.
Inside the container, edit the file my.cnf and check for the line that begins bind-address. Put a hash at the start of the line to comment it out:
#bind-address = 127.0.0.1
Save the file.
While still inside the container, send the shutdown command to MariaDB. This will shut down the server and also exit back out to the host:
mysqladmin -u root -p shutdown
Start the container again. This time the MariaDB server will have networking enabled:
docker start mariadbtest
Find the IP address that has been assigned to the container:
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mariadbtest
You can now connect to the MariaDB server using a TCP connection to that IP address.
Forcing a TCP Connection
After enabling network connections in MariaDB as described above, we will be able to connect to the server from outside the container.
On the host, run the client and set the server address ("-h") to the container's IP address that you found in the previous step:
mysql -h 172.17.0.2 -u root -p
This simple form of the connection should work in most situations. Depending on your configuration, it may also be necessary to specify the port for the server or to force TCP mode:
mysql -h 172.17.0.2 -P 3306 --protocol=TCP -u root -p
Port Configuration for Clustered Containers and Replication
Multiple MariaDB servers running in separate Docker containers can connect to each other using TCP. This is useful for forming a Galera cluster or for replication.
When running a cluster or a replication setup via Docker, we will want the containers to use different ports. The fastest way to achieve this is mapping the containers ports to different port on our system. We can do this when creating the containers (docker run command), by using the -p option, several times if necessary. For example, for Galera nodes we will use a mapping similar to this one:
-p 4306:3306 -p 5567:5567 -p 5444:5444 -p 5568:5568
First access the container terminal
docker exec -it some-mariadb bash
'some-mariadb' is the mysql container name
Then access the db directly using the mysql terminal command
mysql -u root -p
Connect to MariaDB from the MySQL command line client
The following command starts another mariadb container instance and runs the mysql command line client against your original mariadb container, allowing you to execute SQL statements against your database instance:
$ docker run -it --link some-mariadb:mysql --rm mariadb sh -c 'exec mysql -h"$MYSQL_PORT_3306_TCP_ADDR" -P"$MYSQL_PORT_3306_TCP_PORT" -uroot -p"$MYSQL_ENV_MYSQL_ROOT_PASSWORD"'
... where some-mariadb is the name of your original mariadb container.
More information about the MySQL command line client can be found in the MySQL documentation
Refer: https://hub.docker.com/_/mariadb/
Slightly different syntax, docker 18.05.0-ce on ubuntu 18.04:
sudo docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' db

Connect to MySQL via ssh tunnel to localhost

I want to connect to remote MySQL via ssh tunnel with user that has 'localhost' access.
I use this to make a tunnel:
ssh -f -N -L 33306:localhost:3306 user#remote-host
and this to connect to host:
mysql -h 127.0.0.1 -P 33306 -uuser -ppassword
The error i get is:
ERROR 1045 (28000): Access denied for user 'user'#'remote-host' (using password: YES)
The problem is that user 'user'#'remote-host' (or 'user'#'%') does not exist, only 'user'#'localhost' does.
Is there a way to force remote host, without server-side modifications into thinking that i come from localhost? That's the only reason I would do the connection via ssh tunnel anyway.
Note:
If I want to connect with this command:
mysql -h localhost -P 33306 -uuser -ppassword
I get this error:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
Additional data:
On remote server in /etc/hosts the values are like this:
127.0.0.1 localhost
remote-ip remote-host
The simple way to create MySQL Tunnel to REMOTE HOST:
$ ssh -fNL TEMP_PORT:localhost:MYSQL_SERVER_PORT USER#SERVER_NAME
Test:
$ mysql -u root -p -h 127.0.0.1 -P TEMP_PORT
Please note that localhost and 127.0.0.1 are treated differently in mysql on unix.
Quoting:
On Unix, MySQL programs treat the host name localhost specially, in a way that is likely different from what you expect compared to other network-based programs. For connections to localhost, MySQL programs attempt to connect to the local server by using a Unix socket file
http://dev.mysql.com/doc/refman/5.7/en/connecting.html:
Furthermore, mysql client would silently try to use a socket file even if you explicitly specify -P on your command line:
This occurs even if a --port or -P option is given to specify a port number. To ensure that the client makes a TCP/IP connection to the local server, use --host or -h to specify a host name value of 127.0.0.1
Effectively, using this command
mysql -h localhost -P 33306 -uuser -ppassword
you're simply trying to connect to your local mysqld which is missing
Considering this, your question boils down to connecting to a remote server available over a domain socket.
If installing additional software meets your requirements 'without server-side modifications' you could use socat as described here:
https://www.debian-administration.org/users/dkg/weblog/68.
Tailored for mysql, it could work as follows:
install socat on both ends
socat "UNIX-LISTEN:your_local_path/mysql.sock,reuseaddr,fork" EXEC:'ssh user#remote-host socat STDIO UNIX-CONNECT\:/your_server_path/mysql.sock"
mysql -S your_local_path/mysql.sock -u user