What I want
There is the https://github.com/jwilder/nginx-proxy package. This is very useful for "HTTP", but I want to use it to TCP too. (MySQL)
Here are my changes: https://github.com/fchris82/nginx-proxy/commit/33d80ea4d4be5d511e4dab0413d516770aa15262
As you can see, I have added stream {} block to nginx.conf and the /etc/nginx/stream.conf.d directory. Here is the generated default.conf for stream block:
access_log off;
error_log /var/log/nginx/debug.log debug;
resolver 127.0.0.11;
# whoami.loc
upstream whoami.loc {
## Can be connect with "nginxproxy_default" network
# nginxproxy_mysql_1
server 192.168.32.2:3306;
}
server {
listen whoami.loc:81;
proxy_pass whoami.loc;
}
What I did, how can you reproduce the error
# Set host
> sudo echo "127.0.0.1 whoami.loc" >> /etc/hosts
# Start containers
> docker-compose up -d
# "Login" the proxy container
> docker-compose exec nginx-proxy /bin/bash
# Test connect to MySQL from proxy container
root> mysql -u root -proot -h whoami.loc -P 81
# --> OK, it works! Let's exit.
mariadb> \q
# Exit from container
root> exit
# Check host
> ping whoami.loc
# --> OK, 127.0.0.1
# Check docker ports
> docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------------------------------------------
nginxproxy_mysql_1 docker-entrypoint.sh mysqld Up 3306/tcp
nginxproxy_nginx-proxy_1 /app/docker-entrypoint.sh ... Up 0.0.0.0:180->80/tcp, 0.0.0.0:81->81/tcp
nginxproxy_whoami_1 /app/http Up 8000/tcp
# --> OK
# Try to direct connection from host (You can read the IP from the /etc/nginx/stream.conf.d/default.conf file)
> mysql -u root -proot -h 192.168.32.2
# --> OK, exit
mysql> \q
# Try to connect from host with "domain" through docker proxy
> mysql -u root -proot -H whoami.loc -P 81 --protocol=tcp
# ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 2
So, has anybody idea why works from container but why doesn't work from host?
The "solution"
There isn't solution for what I realy wanted. I wanted something like this: Nginx TCP forwarding based on hostname . Tarun's answer solved the error message, thank you.
You need to make sure that
server {
listen whoami.loc:81;
proxy_pass whoami.loc;
}
I getting generated as
server {
listen 81;
proxy_pass whoami.loc;
}
Because for your original config to work, it needs a host entry in /etc/hosts for whoami.loc. And if you make the host entry as 127.0.0.1 then it will only listen to localhost inside the container. And the connections from outside won't be answered.
That is the reason after making the host entry and restart nginx, it worked from inside the container but not from the host. Because it became a effect listen as 127.0.0.1:81
Related
I'm running a mysql 8 server on a custom port using docker and try to connect to it with command line client using the below command
`mysql -uroot -p -P 3305 --protocol=TCP -h localhost`
Error Response
ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (61)
Docker Compose File
version: '3'
services:
mysqldb:
image: mysql:8
ports:
- 3305:3306
environment:
- MYSQL_ROOT_PASSWORD=MyRootPass
- MYSQL_USER=myuser
- MYSQL_PASSWORD=myuserpass
- MYSQL_DATABASE=mydb
volumes:
- ../lcdatastore/mysql/data:/var/lib/mysql
But i'm able to connect to the mysql if the mysql is run using docker run command
docker run -e MYSQL_ROOT_PASSWORD=MyRootPass -e MYSQL_USER=myuser -e MYSQL_PASSWORD=myuserpass -e MYSQL_DATABASE=mydb -p 3305:3306 mysql:8
Thanks for any hint
Update
I'm checking this on macOS Catalina (Version 10.15.2)
I see two possible issues here. The first one is not the case for you in particular, I'm just leaving this here for anyone landing here in the future with that problem:
From the mysql docs:
If the host is not specified or is localhost, a connection to the local host occurs:
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: the client connects using a Unix socket file. The --socket option or the MYSQL_UNIX_PORT environment variable may be used to specify the socket name.
I.e. when using localhost as the host mysql tries to connect via a unix socket and not via network. The former won't work on your macOS host since only the latter will pass the connection to the container.
You can force the connection via network by using 127.0.0.1 as the host or by passing the --protocol=TCP parameter (which you did in your question):
mysql -uroot -p -P 3305 -h 127.0.0.1
mysql -uroot -p -P 3305 --protocol=TCP -h localhost
The second issue may be that the port is not correctly forwarded from the macOS host to the docker host:
Since docker uses Linux namespaces for its containers it does not actually work on macOS natively. What it does instead is to transparently start a Linux VM in the background - which is the actual docker host - and forwards all docker commands to that VM. So the containers are not actually running on macOS but inside a Linux VM.
So when a container exposes a port to the "host" this refers to Linux VM and not the macOS host. From the perspective of the mysql run on macOS localhostrefers to the macOS host and not the docker host (i.e. the Linux VM).
Normally docker will set up respective port forwardings from the macOS host to the Linux VM automatically to make this work as you expect it. But this seems to be broken in your case. To further debug this, first try to connect to mysql on the Linux VM directly:
# start a new container attached to the host network (i.e. the network of the Linux VM)
# "127.0.0.1" will force a network connection
# and "3305" therfor refers to the localhost on the docker host
docker run --network=host -ti mysql:8 mysql -u root -p -P 3305 -h 127.0.0.1
If this succeeds the docker networking is basically working correctly (inside the Linux VM) and there is an issue with forwarding ports from macOS to the VM.
Now:
check if port 3305 on macOS is accepting connections, e.g. with netcat, with and without the mysqldb service running
check which process is listening on 3305, e.g. with netstat or see Who is listening on a given TCP port on Mac OS X?
I'm new to Docker and I can't seem to get my mariadb container running. I have just freshly installed Docker on Macbook Pro running High Sierra.
I've simple used this command:
docker run --name db -e MYSQL_ROOT_PASSWORD=test -d -p 3306:3306
mariadb
Which is supposed to create an image and run the container from it. But I get the following error:
docker: Error response from daemon: driver failed programming
external connectivity on endpoint db
(d4d6631ae53d644b5c28a803d5814a792c7af6925ebcf84b61b49b4a0fe30f4b):
Error starting userland proxy: Bind for 0.0.0.0:3306 failed: port is
already allocated.
So far I may have used MySQL in the far past, but I'm pretty sure I don't have anything running on port 3306.
I have also tried not adding the -p tag, it will run when I use this but when i execute docker ps it will show 3306/tcp and NOT 0.0.0.0:3306->3306/tcp as the PORT.
I have also tried just having to port tag as -p 3306 but this will show 0.0.0.0:32769->3306/tcp as the PORT in docker ps.
I would love some help. Thanks in advance.
Use lsof command to check if a service / process is using the port 3306.
$ lsof -i tcp:3306
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 721 krisnik 34u IPv4 0x348c24a60c9d72a9 0t0 TCP localhost:mysql (LISTEN)
Now kill / stop the service.
kill -9 <PID>
Re-run your Docker container. It should work fine as the required port is released.
Edit - 1
If lsof doesn't catch the process, netstat can also be used.
sudo netstat -lpn |grep :3306
kill -9 PID //PID processID used by 3306 Port
Ref - Port 3306 busy but no process using it
sudo docker run -i -t f92f0896ed95 /bin/bash
[Entrypoint] MySQL Docker Image 5.7.21-1.1.3
bash-4.2# mysql
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
bash-4.2#
You have to configure ~/.my.cnf with your credentials, then mysql shell can be opened directly.
Example of content :
[client]
user=dba
password=foobar
# depends of what is configured, can be a hostname or 127.0.0.1, it's matter :
host=localhost
Or if you can't configure the image, do this :
mysql -h localhost -p
Then you will be prompted to enter the password
First run your image standard and then connect to the running image with:
docker exec -it f92f0896ed95 /bin/sh
On my AWS ec2 server I have docker 1.9.1 installed.
In an image test_image based from ubuntu:trusty official docker image, I have tried to setup the LEMP(Linux, Nginx, MySQL, PHP) architecture.
Following is the docker command i have used to start my container:
docker run --name test_1 -d -p 80:80 -p 3306:3306 test_image /bin/sh -c "while true; do echo daemonized docker container; sleep 5000; done"
I have exposed port 80 and 3306 to the host's network interface and have also allowed AWS's security group to allow inbound connections to these ports. Connection type in security group is: MYSQL/Aurora and protocol is: TCP (I know its not very secure, its only for initial implementation. Production setup will be different)
I followed this DigitalOcean tutorial: https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mysql-php-lemp-stack-on-ubuntu-14-04
After installing Nginx and starting it I am able to test it in the browser via ec2's pubic ip i.e. http://xxx.xxx.xxx.xxx shows the default nginx welcome page.
While installing MySQL, I followed the following commands in the docker container:
apt-get install mysql-server
mysql_install_db
/etc/init.d/mysql start
mysql_secure_installation
I have given a password to my root user and during mysql_secure_installation i had allowed remote access to root user.
mysql -u root -p command from inside the container connects me to the mysql db but not from outside the container.
Also from my local machine:
I tried with mysql-client:
mysql -h xxx.xxx.xxx.xxx -u root -p
I got the following error: ERROR 2003 (HY000): Can't connect to MySQL server on 'xxx.xxx.xxx.xxx' (111)
and also through mysql workbench but I still can't connect to the mysql db.
What am I doing wrong?
In your host mysql's my.cnf set the bind address to 0.0.0.0 so that mysql listens on all network interfaces
bind-address = 0.0.0.0
The default config is:
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address = 127.0.0.1
How to configure two different port for MySQL on same machine? I know that default port is 3306. But I also want to configure 3307 and 3308. Is it possible?
One bonus question with current one ;)
Can we assign Different Ports to Different Databases and also can assign/create Credentials respectively?
You can use the --port=port_num option. Have a look here for more information on how to configure multiple mysql instances.
You can launch several instance of mysql :
mysqld_safe --defaults-file=/path/to/my.cnf1
mysqld_safe --defaults-file=/path/to/my.cnf2
mysqld_safe --defaults-file=/path/to/my.cnf3
and change the port parameter in the [mysqld] section of each my.cnf.
If you want to have only one mysqld process/database you can use port redirection (with linux) :
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 3307 -j REDIRECT --to-port 3306
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 3308 -j REDIRECT --to-port 3306
You can copy /etc/mysql/my.cnf, change the port in it and change the pathes to data dirs as well, because i'm pretty sure You can't have more than 1 instance of mysql serving from the same directories.
Check http://dev.mysql.com/doc/refman/5.1/en/multiple-servers.html.
ex :
cp /etc/mysql/my.cnf /etc/mysql/my-3307.cnf
//edit my-3307.cnf, for example
port = 3307
basedir = /var/lib/mysql-3307
datadir = /var/lib/mysql-3307
//end-edit
mysql_upgrade --defaults-file=/etc/mysql/my-3307.cnf #checks the syntax and creates the dirs you need.
#start mysqld
mysqld --defaults-file=/etc/mysql/my-3307.cnf
mysqld_multi is by far the best way to handle different instances of mysql.
Some more useful tips:
mysqld_multi --example
check if apparmor isn't keeping mysql from accessing /var/lib/mysql2 if you get weird permission errors.
I'm using CentOS.
Not is too simple,
Edit file /etc/my.cnf, Search and change or add line: port=port_number.
semanage port -a -t mysqld_port_t -p tcp port_number
Restart MySQL Server. service mysqld restart