Can't access MySQL Docker container remotely - mysql

I have the following docker-compose.yml configuration:
version: "3.9"
services:
db:
image: "mysql:8.0.23"
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_ROOT_PASSWORD=somethingsomething
volumes:
- /home/gutta-server/Servers/mysql/hvb_db:/var/lib/mysql
ports:
- 3306:3306
expose:
- 3306
adminer:
image: "adminer:4.8.0-standalone"
restart: always
ports:
- 7000:8080
I have also opened ports 3306 and 7000 on the router that the host is connected to. Going to <my-domain>:7000 in my browser, from an external network, I am able to log in to Adminer and manage my database. I have also ran ufw allow 3306 on the host.
It's also worth noting that running telnet localhost 3306 on the host server (the one that actually runs the container) works, and confirms to me that the local port mapping is working just fine.
However, running the same command, just as telnet <my-domain> 3306 from a remote computer, not on the same network, yields the following:
Trying <my-domain's-ip>...
telnet: Unable to connect to remote host: Resource temporarily unavailable
Therefore, something must be wrong with the remote connection, not the actual database itself.
I feel like I've scoured SO dry, but having experience with these forums, surely someone will links this exact issue :p Anyway, here are the things I've tried:
Port forwarding port 3306 in router configuration (I have other port forwards too, which work perfectly fine, shouldn't be a router or ISP issue)
Allowing port 3306 though the host's firewall (ufw allow 3306)
Add bind-address = 0.0.0.0 to the container's /etc/mysql/my.cnf file and restarting the container (docker-compose restart doesn't remove this entry, stopping and starting does. I would solve this with a volume if it actually solved the issue, but it didn't)
Completely disable ufw (after suggestion in comments)
I literally can't think of a single other thing that could possibly be wrong, and I can't find anything more on the internet, either..
I really hope I've provided enough information here, please do let me know if anything else is needed.

Related

ECONNREFUSED when connecting from dockarized node.js but works in workbench

I have been having troubles reaching mysql server from my dockarized nodejs app. I can access the database normally with localhost, port 3307, password, user and database in workbenceh so I assumed I can just do the same in my nodejs app but with 3306.
No matter what configuration I have tried I've always gotten the -111, ECONNREFUSED, connect... error back.
Mysql server is ready for connections before nodejs starts and is listening on 3306. I have the right users with the right privelages... I really don't know what I am missing at this point.
version: '3.3'
services:
db:
image: mysql:8
restart: always
volumes:
- db:/var/lib/mysql
env_file: ./.env
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: database
MYSQL_ROOT_USER: user
ports:
- 3307:3306
app:
container_name: app_con
build: ./
restart: always
env_file: ./.env
ports:
- 5000:5000
stdin_open: true
tty: true
depends_on:
- db
volumes:
db:
My node.js connection:
const pool = mysql.createPool({
connectionLimit: 15,
host: localhost, /*I have tried 127.0.0.1, 0.0.0.0, 172..., my lan ip*/
user: user,
password: password,
port: 3306, /*I have also tried 3307*/
database: database,
multipleStatements: true
});
I am going to try this once.
A container is actually just a process, BUT it acts like a vm. It has its own hostname and IP address. This means "localhost" inside one container refers to that container. Not the host, not the other container.
As they have their own IPs, containers connect to each other over virtual networks using those IPs. When they connect like this, they can connect to ANY port being listened on by services in the other. They use each others IP address, or service name to connect over these virtual networks. container to container networking does NOT use "EXPOSE", "PUBLISH", "Ports", "-" etc. directives and there is no port remapping. If software listens on port :80, then connecting software must connect on port :80
The "ports:" directive, or "-p" on the docker run command is used to publish a port from a container to the host. This bridges a port from the container, to the host. "-p 1234:5678" This will make port 1234 on the host bridge through, and communicate with 5678 in the container. "Ports" "Publish" and "Expose" are purely used for container to host networking.
Putting this together:
When "app" tries to conenct to "db", it must use "db:3306" for the connection. Regardless of what Ports might say, or if there is a Ports directive at all. If the service name is "mysqldb" then the connection string must be "mysqldb:3306".
If you are trying to connect to the db from your desktop, then you must use the port from the lhs of the ports directive, plus localhost, because thats the bridged end of the port. i.e. "3307:3306" means that "locolhost:3307" would be used from a desktop tool to reach into docker to reach the mysql container, and connect to it on its :3306 port.
The rhs of the ports directive for "app" must be whatever the nodejs app is actually listening on. If the nodejs app listens on :5000, then the rhs must be 5000. If there is a message about the port being unavialable, then its unavailable inside the container, and the app needs to be configured to listen on a different port, and the ports directive needs to change to reflect that.
The lhs port can be any port that is not used on the host, that is easy and convenient to use in your browser. E.g. "8080". Setting app's Ports directive to - 8080:5000 would let you enter http://localhost:8080 in your desktop browser to access the app. Just make sure the nodejs app is listening on :5000.

Docker-Compose Services Not Communicating

Docker noob alert. Hope this isn't a dumb question but I cannot seem to figure out what is going on. I am trying to create a docker-compose file which creates a mysql db with a mounted volume and a go webserver app that connects to the mysql db.
Here is my docker-compose file:
services:
db:
image: mysql:8.0.2
environment:
MYSQL_ROOT_PASSWORD: test
MYSQL_DATABASE: northernairport
ports:
- "3306:3306"
volumes:
- /data:/var/lib/mysql
web:
depends_on:
- db
build: .
ports:
- "8080:8080"
My go application can't seem to connect to my mysql db though, I thought the "depends_on" would ensure this was possible.
Error I get:
panic: dial tcp 127.0.0.1:3306: getsockopt: connection refused
Can anyone tell me what I am doing wrong here? Thanks.
The depends_on only controls the build and startup order for the services.
Your actual issue is more likely that you are using the wrong address from your web application to your database. I see that you have not defined any networks, so you are using the default network created for your application by docker-compose. This will publish each service by name on the default network's DNS.
So, your web application should probably be using db:3306 as the database address, not localhost:3306 or 127.0.0.1:3306 as indicated in the error message.
The ports part is used to map container ports with host in following format ports (HOST:CONTAINER). Which means that you are trying to access host's machine, configure web app to connect to db:3306 instead.

Docker gogs connection is refused by mysql container

I have some trouble with setting my local git repository. I am new to docker, so the problem may be naive but I still can't find it.
So my idea is:
I wanted to create a container with gogs (gogs/gogs image) and connect it to mysql container.
To do so I have created docker-compose.yml file.
version: '3'
services:
db:
image: mysql
ports:
- "10023:3306"
environment:
- MYSQL_ROOT_PASSWORD=root!
ui:
image: phpmyadmin/phpmyadmin
ports:
- "8989:80"
links:
- db:mysql
repo:
image: gogs/gogs
ports:
- "10022:22"
- "10080:3000"
volumes:
- /tmp/gogs:/data gogs/gogs
links:
- db:mysql
I all put phpmyadmin in my setup, this way I can easily test if mysql is up and respond to other containers.
Sadly this environment does't work, when get to gogs install page on localhost:10080 and try to create a new repo, it says that tcp connection has been refused. This is the output of the error message:
dial tcp 127.0.0.1:10023: getsockopt: connection refused
This is strange, because I can access to mysql container through phpmyadmin. I also was able to create gogs database.
Do anybody had this issue before?
Don't use localhost or 127.0.0.1 from inside the container, use the service name as defined in your docker-compose.
dial tcp db:10023
docker-compose networking.
Thank a lot to gogsdoc_db_1. His/her answer is perfect. I will try to explain what I have done wrong, so maybe this would help new entry in docker such as myself.
As bluescores, have said. You shouldn't use localhost or 127.0.0.1 inside you docker container.
Why not?
Basically, when you use docker-compose it automatically create shared network for your app, which means you shouldn't use the published port.
In may case I must use port 3306, instead of 10023 to connect to my database container.
I should still use port 10023 if I want to connect to mysql from my local machine.
so my configuration now is
P.S.
Do not forget to create the database, before you install gogs

How to connect to a MySQL Docker Container via SSH?

When I try to tunnel via SSH to the Host Mashine (vServer) and then try to connect via the internal docker Container-IP then I can't connect to MySQL.
This is my docker-compose file.
version: '2'
services:
mysql:
build: ./mysql
environment:
MYSQL_ROOT_PASSWORD: test
volumes:
- ./db:/var/lib/mysql
The only solution I found was to forward the MySQL-Port of the mysql container to the Host-Mashine.
version: '2'
services:
mysql:
build: ./mysql
environment:
MYSQL_ROOT_PASSWORD: test
volumes:
- ./db:/var/lib/mysql
ports:
- 3306:3306
Then I am able to connect via the Host IP to MySQL but this is without SSH its direct via TCP and the port.
This is a No-Go for me to bring the MySQL Service into the internet.
Reasons can be found here https://security.stackexchange.com/questions/63881/is-it-not-safe-to-open-mysqls-port-to-the-internet why it is not a good practice to bring your mysql port into the internet.
So what is a good practice to connect to my docker mysql container with SSH but keep the mysql ports closed?
One simple way is to bind the MySQL port only to the localhost address. That assumes the host has a mysql client available outside of Docker.
ports:
- 127.0.0.1:3306:3306
You could also omit the ports section completely (no port binding at all), and use the mysql client that's already inside the container.
docker-compose exec mysql bash
Then run the mysql command inside the container to do whatever queries you want to do.
An easy way to achieve this is to forward the ssh port of the docker conatiner to some port on your host, i.e.
ports:
- 22:<some free host port>
and then access the container via ssh to the host port you used. Note, that it is a bad idea to use port 22, since that will cause a conflict with the ssh server running on your host.

Get database address with Docker

I use docker-compose with the following docker-compose.yml:
web_db:
image: mariadb:latest
restart: always
volumes:
- ./var/mysql:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: X
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: X
MYSQL_ROOT_PASSWORD: X
web_front:
image: nginx
restart: always
ports:
- 80:80
links:
- web_fpm
volumes:
- ./www:/var/www/html:rw
- ./etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
web_fpm:
build: ./PHP-FPM/
restart: always
links:
- web_db:mysql
volumes:
- ./www:/var/www/html
When configuring Wordpress (manually downloaded in nginx root directory), I'm asked for the address of the database. I've tried localhost, but it doesn't work.
PS: I know there are Wordpress images for Docker, but they have the full stack (nginx + PHP) and I don't like it, so don't propose them. ;)
Try 'web_db' instead of localhost
https://docs.docker.com/compose/compose-file/
Containers for the linked service will be reachable at a hostname identical to the alias, or the service name if no alias was specified.
You need to reference mysql because in your compose file you have linked your container to the web_db container and given it an alias of 'mysql'. The web_fpm container will have a record in it's hosts file for mysql which will point to the web_db container.
Alternatively, if you just want to get the ip to enter manually, just run docker inspect <web_db_container_id>
edit: You will want to put in the IP of the host machine along with port 3306 and here is why.
When starting a container with Docker it is started using an IP assigned from the Docker. These are all accessible to docker via the docker0 bridged network. Docker in turn makes those accessible to the host machine by bridging the docker0 NIC on the host machine with the host machines eth0/1 ect.
When you EXPOSE a port explicitly via docker run -td -p <some external port>:<some internal port> Docker opens that port up in the host IPTables so it is accessible on the local network. If you do not explicitly open the port but it is exposed in the container (the docker file will say EXPOSE 3306 for MySQL in its Dockerfile.) then the container is only available to the machine.
Now, when working with Docker containers it's important to know this because when you do a link with docker-compose you are only telling that container where another container is on the local docker network. This only helps if you have containers that start and are looking for a dependent container.
To summarize, when containers are started they are started with a Docker IP that is only used by Docker and bridged back to the host machine via docker0, and this is key. Docker isolates those IP and forces you to either open the ports on the machine to access via your local network.
Back to your question and why you need to pass it the host IP and port 3306.
You need to do this because you are making making a request on your network. If you put in localhost it will not work because the container is not really running on localhost it's running on some 172.17.42.x address so telling WordPress it's on localhost, it's not. It is however on at the host machines IP because the host machine is bridged to docker0. This is why you have to give it the host machines IP. Because you network can't resolve the 172.17 address since that is specific to Docker and specific to that machines containers. This is very fundamental to Docker networking and important to understand. See this article for more information.