Docker-Compose Services Not Communicating - mysql

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.

Related

Why won't TeamCity connect to MySQL when using docker-compose?

I'm trying to get TeamCity server running using docker-compose. Here's my compose file:
version: '3'
services:
db:
image: mysql
container_name: teamcity-db
restart: unless-stopped
env_file: .env
environment:
- MYSQL_DATABASE=teamcity
volumes:
- mysql:/var/lib/mysql
command: '--default-authentication-plugin=mysql_native_password'
teamcity:
depends_on:
- db
image: jetbrains/teamcity-server
container_name: teamcity
restart: unless-stopped
volumes:
- datadir:/data/teamcity_server/datadir
- logs:/opt/teamcity/logs
ports:
- "8111:8111"
volumes:
mysql:
datadir:
logs:
I've been successful getting wordpress set up using a very similar technique, and I can run phpMyAdmin and link it to the MySQL container and see the database, so its there.
When I browse to the teamcity web address, it shows me the initial setup screen as expected. I tell it to use MySQL and I put in 'root' as teh username and my MySQL root password. Teamcity then shows this:
I'm sure it's something simple but I just can't see what's wrong. Any ideas?
Solved! Here is my solution and some other learnings.
The problem was that I was telling TeamCity to use 'localhost' as the database server URL. This seems intuitive because all the services are on the same machine, but is incorrect. It is as if each container is its own host and so 'localhost' is specific to each container. 'localhost' inside a container refers to the container itself, not the host machine or any other container. So 'localhost' on the teamcity service refers to the teamcity server, not the database server, and that's why it couldn't connect.
The correct address for the database server based on my docker-compose.yml file is db (the service name of the database container). The service name becomes the host name for that container and docker resolves these as DNS names correctly within the composed group.
Also note: the default virtual network is created implicitly by docker-compose and allows all of the containers in the composed group to communicate with each other. The name of this network derives from the folder where the docker-compose.yml file is located (in my case ~/projects/teamcity) so I get a network called teamcity_default. All servers on this private vitual network are visible to each other with no further configuration needed.
The teamcity server container explicitly exposes port 8111 on the host's network interface, so it is the only container visible to the outside world. You do not need to (and probably should not) expose ports if you only need the servers to talk to each other. For example, the database server does not need to have a ports entry because it is automatically exposed on the private inter-container network. This is great for security because all the back-end services are hidden from the physical LAN and therefore the Internet.

Unable to connect to mysql container defined in docker-compose using service name

I have the following docker-compose.yml
version: '3'
services:
app:
build: .
network_mode: host
volumes:
- .:/usr/usr/src/app
db:
image: mysql/mysql-server:5.7
environment:
MYSQL_DATABASE: config_dev
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
- ./docker/images/config-dev-image/sql-scripts:/docker-entrypoint-initdb.d
restart: always
ports:
- "1200:3306"
My app service needs to connect to the db and using the documentation I tried to connect to using the service-name 'db' like so (from the app container)
mysql --hostname=db --port=3306 --user=root However, I get the error ERROR 2005 (HY000): Unknown MySQL server host 'db'
What am I doing wrong?
Your app container is running with network_mode: host. If it's using the host network then it can't use any of the Docker-specific network features; for example, it can't reach other containers by host name and it can't be reached by host name. For Docker networking purposes it's indistinguishable from a process running on the host.
Host networking isn't actually necessary for most of the cases I see suggested on SO, and you should see if your application works if you just remove that line. You might need to add ports: to make it accessible from outside.
If you really can't disable host networking, then you need to connect to the database the same way other processes running outside Docker network space would, via the other container's published ports. A host name of localhost should work (because you're in the context of the host) but you need the mapped port number --port=1200.
Add links configuration in app section
version: '3'
services:
app:
build: .
network_mode: host
volumes:
- .:/usr/usr/src/app
links:
- db
db:
image: mysql/mysql-server:5.7
environment:
MYSQL_DATABASE: config_dev
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
- ./docker/images/config-dev-image/sql-scripts:/docker-entrypoint-initdb.d
restart: always
ports:
- "1200:3306"
Because of network_mode: host your app container is effectively on a docker's private network like 192.168.65.1/24 while you db container is on a different private network created by docker-compose like 172.20.0.2/16. You can see this network being deleted when you run docker-compose down:
Removing network XXXX_default
where XXXX is your directory name.
If you were to remove network_mode: host from service app, both containers would be on the same private network and reachable by their service name.
$ docker inspect XXXX_default
"Containers": {
...
"Name": "app",
"IPv4Address": "172.21.0.3/16",
...
},
...
"Name": "db",
"IPv4Address": "172.21.0.2/16",
...
}
},
app container can access db on port 3306. No need to expose the port as 1200. As per docs:
Containers connected to the same user-defined bridge network
automatically expose all ports to each other, and no ports to the
outside world. This allows containerized applications to communicate
with each other easily, without accidentally opening access to the
outside world.

Can't connect to database: Access denied for user

I am setting up a CakePHP 3.7 application and using docker compose. I have a mysql service as well that I'm trying to connect to, but I am getting this error: Access denied for user 'ws_user'#'172.20.0.3' (using password: YES)
I am granting permissions to the user like so: GRANT ALL PRIVILEGES ON mydb.* TO 'ws_user'#'%' IDENTIFIED BY '<superSecretPasswordHere>'.
If I use the root credentials, cakephp is able to make the connection just fine.
I also expose the mysql service on port 3030 to my local machine and I am able to connect with the ws_user credentials just fine.
I also setup mysql running on my local machine with the same credentials and cake is able to connect to host 172.17.0.1 just fine as well.
I'm perplexed as what could be the problem. It sure seems like it's a permissions problem (because of the error message), but I'm able to connect via the exposed port via the command line. My next thought was that it might be because of special characters in the password, but again, if I connect to mysql running on my host machine, it works fine with the same password.
Here is my docker-compose file:
version: '2'
# define all services
services:
# our service is called CakePHP ;-)
cakephp:
# we want to use the image which is build from our Dockerfile
build:
context: .
dockerfile: Dockerfile
# apache is running on port 80 but we want to expose this to port 4000 on our local machine
ports:
- "80:80"
# we are depending on the mysql backend
depends_on:
- mysql
# we mount the working dir into the container, handy for development
volumes:
- .:/var/www/html/
environment:
- SECURITY_SALT
- MYSQL_HOST
- MYSQL_USERNAME
- MYSQL_PASSWORD
mysql:
# we use the mysql base image, version 5.6.36
#image: mysql:5.6.39
build:
context: .
dockerfile: Dockerfile.mysql
ports:
- "3030:3006"
# we mount a datavolume to make sure we don't lose data
volumes:
- mysql_data:/var/lib/mysql
# setting some envvars to create the DB
environment:
- MYSQL_ROOT_PASSWORD
- MYSQL_DATABASE
volumes:
mysql_data:
From "cakephp" you connect to "mysql:3306". This should be in your connection string.
From your host you can connect to "127.0.0.1:3030" to verify that your database accepts remote login.
Then you should check the credentials that they are the same. I suggest you put them in a .env file and then test the connection by "copy-paste" of the values.
you can check the values that are actually passed to the containers by running:
docker-compose config
This shows you the exact version of the docker-compose file that will be sent to the docker engine.
Hope this works, otherwise drop me a comment.

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.