84

Through docker-compose.yml I am able to run the application. Now we want to move the application to production, But we don't want to use the container database. So is there any way so that I can connect my local MySQL database with the application using docker-compose?

My docker-compose.yml looks like:

version: '3'
services:
  web-app:
    build:
      context: .
      dockerfile: web-app/Dockerfile
    ports:
      - 8080:8080
    links:
      - app-db

  app-db:
    build:
      context: .
      dockerfile: app-db/Dockerfile

    environment:
    - MYSQL_ROOT_PASSWORD=password
    - MYSQL_DATABASE=Optimize
    ports:
      - 3306:3306

Instead of app-db part I just want to connect to my locally hosted mysql database.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Prateek Naik
  • 2,522
  • 4
  • 18
  • 38
  • 1
    Possible duplicate of [From inside of a Docker container, how do I connect to the localhost of the machine?](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach) – Iman Jun 14 '17 at 12:21

8 Answers8

138

Just use host.docker.internal instead of localhost.

To make it work on Linux, you just need to start your Docker container passing the parameter --add-host host.docker.internal:host-gateway

Júlio Falbo
  • 1,756
  • 1
  • 9
  • 11
  • 7
    You just saved my life! I love you. This should be the accepted answer, or added to the accepted answer for all to know! – sboy Jul 22 '20 at 09:10
  • 2
    @Júlio Falbo: At which point exactly can I use "host.docker.internal" instead of "localhost"? Could you elaborate a little? Thank you!! – Tortoise Nov 11 '20 at 09:32
  • Sure. In your client application. In the case above we can use it in the db configurations of the `web-app`, so, instead of `localhost` we use `host.docker.internal`. – Júlio Falbo Nov 11 '20 at 10:59
  • 2
    Why this is not working for me? If I ping from inside a container I saw "host not found" – Kreker Feb 11 '21 at 14:46
  • @JúlioFalbo changed localhost to host.docker.internal in my app's settings but I get the following Error: django.db.utils.OperationalError: (2005, "Unknown MySQL server host 'host.docker.internal' (-2)"). I am using docker version 1.20. what could be the issue? – Philip Mutua May 10 '21 at 05:14
  • @PhilipMutua, If you are using Linux, you just need to start your Docker container passing the paraneter `--add-host host.docker.internal:host-gateway`. – Júlio Falbo Jun 01 '21 at 12:32
  • Just to clarify, i set env variable `PGHOST: host.docker.internal` for my expressjs server in docker-compose. It was `localhost` before, and this fixed the `ECONNREFUSED` – element11 Aug 30 '21 at 14:26
  • Also you should have docker version 20.10+ (works on 20.10.12). In docker-compose you can use `extra_hosts: - "host.docker.internal:host-gateway" ` – Dmitry Davydov Feb 13 '22 at 06:56
  • in my case, docker run -d --restart always --name vaultwarden \ --add-host host.docker.internal:host-gateway \ -e DATABASE_URL=mysql://admin:*******@host.docker.internal:3600/vault \ -v /vw-data/:/data/ \ -p 8082:80 \ vaultwarden/server:latest this is my docker command. but I'm still getting this error, [CAUSE] BadConnection( "Can't connect to MySQL server on 'host.docker.internal' (115)", ) – Sathya Molagoda Oct 26 '22 at 17:17
  • On MacOS you maybe wanna use docker.for.mac.host.internal as the hostname – Eugene Jul 07 '23 at 22:04
81

Find the host machine ip in the docker network. If you use docker-compose.yml version: "3" it's probably that that IP is: 172.18.0.1, but confirm it searching for the "Gateway" of your container (your host):

docker inspect <container-id-or-name> | grep Gateway
"Gateway": "",
            "IPv6Gateway": "",
            "Gateway": "172.18.0.1",
            "IPv6Gateway": "",

So inside your docker application point to MySQL as this: 172.18.0.1:3306 (maybe in a configuration file). Take into account that that IP is fixed as long as the docker network still the same (the network is created by docker-compose, and it is not removed unless you do docker-compose down)

Also, check that your MySQL is listening to all of its interfaces. In your my.cnf search for bind-address that should be 0.0.0.0 (consider security issues if your server has public IP).


As an alternative you can bring to the container the same networking as your host, in order to share the localhost, so the container will find mysql there. Use network mode as "host":

version: '3'
services:
  web-app:
    build:
      context: .
      dockerfile: web-app/Dockerfile
    ports:
       - 8080:8080
    network_mode: "host"

Then, point in your hibernate.properties to mysql as this: localhost:3306

Robert
  • 33,429
  • 8
  • 90
  • 94
  • I got `docker inspect | grep Gateway "Gateway": "", "IPv6Gateway": "", "Gateway": "172.19.0.1", "IPv6Gateway": "",` but once i compose, i got this in [log file](https://gist.github.com/Beanben/03b87968283c2207fdb4cdf4544d91b7) – Prateek Naik Jun 14 '17 at 13:12
  • Do you know where is the config file of your app? To update it accordingly – Robert Jun 14 '17 at 13:16
  • you mean web applications `hibernate.properties` file? – Prateek Naik Jun 14 '17 at 13:18
  • Maybe! Do you see the host of mysql there? Try putting 172.19.0.1 and port 3306, that is the IP of your host from docker standpoint – Robert Jun 14 '17 at 13:20
  • in that file i changed `jdbc.url = jdbc:mysql://localhost:3306/optimize1` to `jdbc.url = jdbc:mysql://172.19.0.1:3306/optimize1` but still its not able to connect. Its showing same in the logs as wel – Prateek Naik Jun 14 '17 at 13:25
  • any solution for this ? – Prateek Naik Jun 14 '17 at 15:24
  • 2
    I can't realize what is happening. You have an alternative that is using the `network_mode: host` in the service of you docker-compose.yml. So the container gets the same localhost as your host, so you can point to to mysql as `localhost:3306` – Robert Jun 14 '17 at 16:02
  • can you explain me little bit more. How to add this? – Prateek Naik Jun 14 '17 at 16:20
  • Nope still the same problem. Is there any thing wrong with my web-app's [Dockerfile](https://gist.github.com/Beanben/e2b7cac28d76ebf3a0714e17ef3f16e4) – Prateek Naik Jun 14 '17 at 16:40
  • Your Dockerfile looks ok. I thing that you need to realize the specific error. The logs don't give enough information – Robert Jun 14 '17 at 16:50
  • it just says `Caused by: com.mysql.cj.core.exceptions.CJCommunicationsException: Communications link failure` – Prateek Naik Jun 14 '17 at 16:52
  • Is it your mysql up and running? Check your my.cnf whether it has a `skip-networking` config, should not have it. Check the 3306 port is open – Robert Jun 14 '17 at 16:54
  • Nope it doesn't have. I have also used `bind-address= 0.0.0.0` in `my.cnf` file – Prateek Naik Jun 14 '17 at 17:42
  • What a blunder mistake i did. After making all the changes in `docker-compose.yml` and `hibernate.properties` **i forgot to remove the existing application war file and building war file again**. After doing from the beginning i am able to use my local DB. Thanks man. And i completely ** apologize ** for such lengthy conversations. – Prateek Naik Jun 15 '17 at 09:37
  • @Ben.Bean that kind of things always happend to all of us. Happy to hear that. You're welcome! – Robert Jun 15 '17 at 10:22
  • In docker-compose.yml, is there a way to do "inside your docker application point to MySQL as this ..."? If not, what other technique could be used to make the application container independent of the MYSQL connection details? Somehow create another container that acts as a proxy to the actual database? I'm not sure how to make this convenient for both local development and remote deployment. I don't understand all that must be done to change from using a mysql container db, to using mysql on host pc (windows). I understand the IP issue; I just don't know what to do with that information. – ToolmakerSteve Mar 31 '19 at 12:33
  • Above docker-compose script worked for me. Thanks !! network_mode: "host" – Sidath Bhanuka Randeniya Sep 21 '20 at 18:56
  • I added network mode "host" to my web app and it worked, thanks – Andre Thiele Oct 02 '21 at 12:22
  • It worked with network mode "host", but it doesn't allow port mapping – Diego Feb 18 '22 at 20:32
  • ```network_mode: "host",``` that's what worked for me https://gist.github.com/rintoug/3c7ad792064b622faf062c823d0fc4d2 – Duke Apr 11 '23 at 08:37
8

Allow permission using mysqld.cnf

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address            = 0.0.0.0

save your file and restart mysql server

sudo systemctl restart mysql.service

login to Mysql

mysql -h localhost -u root -p
GRANT ALL ON *.* TO 'root'@'localhost' IDENTIFIED BY 'yourpassword' WITH GRANT OPTION;
GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY 'yourpassword' WITH GRANT OPTION;
FLUSH PRIVILEGES; 
EXIT;

Find your IP

ip addr show

And use it in your docker container 192.168.x.x

Thanuja
  • 119
  • 1
  • 4
  • Which IP I need to use in the application to use localhost database, Is it Docker one or system IP 3: wlp3s0: mtu 1500 qdisc mq state UP group default qlen 1000 link/ether 48:45:20:4f:98:fe brd ff:ff:ff:ff:ff:ff inet 192.168.2.10/24 brd 192.168.2.255 scope global dynamic wlp3s0 valid_lft 5988sec preferred_lft 5988sec inet6 fe80::c273:df61:8eff:65a1/64 scope link valid_lft forever preferred_lft forever – mohan rathour Jul 22 '20 at 08:15
  • 1
    This is in the local machine. But the question was how to do this using docker container – MD SHAYON Dec 12 '21 at 22:37
7

If anybody is using mac os then please use docker.for.mac.host.internal instead of host.docker.internal as the environment variable.

hariAnitha
  • 341
  • 3
  • 5
5

The easist way is use host.docker.internal instead localhost.

MONGO_SERVER = {
'host': 'host.docker.internal',
'port': 27017,
'username': 'admin',
'password': '123456'}
邹伟东
  • 59
  • 1
  • 2
3

Problem:

We had a same scenario where we wanted to setup a Development local machine setup for the services where a developer can just make docker-compose up -d and use all the latest dev builds in his local machine.

But we started facing issues while connecting our tomcat based web service configured as service in the docker-compose.yml to **mysql-8.0** service within the docker-compose. So as alternative and quick fix we thought to use local mysql configured on the local laptop with Ubuntu and docker-compose.

Our tomcat-application was using a application-dev.yml file with jdbc config variable to connect to the mysql, say something like

    url: jdbc:mysql://db:3306/abcDB?useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: abcderf

Docker-compose.yml

version: '3'
services:
      db:
        image: mysql:8.0
        container_name: db
        restart: unless-stopped
        ports:
          - "3306:3306"
        environment:
          - MYSQL_ROOT_PASSWORD=abcd
          - MYSQL_PASSWORD=abcd
          - MYSQL_DATABASE=abcdDB
        volumes: 
          - ./sql-dump:/docker-entrypoint-initdb.d
        command: '--default-authentication-plugin=mysql_native_password'
      
      frontend:
        container_name: frontend
        image: abc/abc:frontend-1.1.36
        depends_on:
          - backend

      nginx:
        container_name: nginx
        image: nginx:1.19-alpine
        links:
          - "frontend"
          - "backend"
        volumes:
          - ./proxyConf:/etc/nginx/conf.d 
        ports:
          - "80:80"
          - "443:443"
      backend:
        container_name: backend
        image: abc/abc:server-3.1.161
        restart: unless-stopped
        env_file: .env
        environment:
          - SPRING_PROFILES_ACTIVE=devtest
          - DB_HOST=db:3306
          - DB_NAME=abcDB
        depends_on:
          - db

Solution worked for us:
As we wanted to connect our docker-compose tomcat service from the local mysql we tried the below routes.

docker inspect <container-id-or-name> | grep Gateway which returned the ip Gateway ip value as`

"Gateway": "",
        "IPv6Gateway": "",
        "Gateway": "172.18.0.1",
        "IPv6Gateway": ""

used the above Ip in the application-dev.yml as below ( URL post resolve of the ${DB_HOST} looks something as below But the IP changes to next highrt post the docker-compose down ex: 172.19.0.1)

    url: jdbc:mysql://172.18.0.1:3306/abcDB?useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: abcderf

Modified docker-compose.yml

version: '3'
services:
      frontend:
        container_name: frontend
        image: abc/abc:frontend-1.1.36
        depends_on:
          - backend

      nginx:
        container_name: nginx
        image: nginx:1.19-alpine
        links:
          - "frontend"
          - "backend"
        volumes:
          - ./proxyConf:/etc/nginx/conf.d 
        ports:
          - "80:80"
          - "443:443"
      backend:
        container_name: backend
        image: abc/abc:server-3.1.161
        restart: unless-stopped
        env_file: .env
        environment:
          - SPRING_PROFILES_ACTIVE=devtest
          - DB_HOST=172.18.0.1:3306
          - DB_NAME=abcDB
        depends_on:
          - db

and Also updated the bind-address = 0.0.0.0 in the /etc/mysql/mysql.conf.d/mysqld.cnf and from the mysql command line allow the root user to connect from any Ip.

Below were the only commands worked for mysql-8.0 as other were failing with error syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IDENTIFIED BY 'abcd'' at line 1

GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost';
UPDATE mysql.user SET host='%' WHERE user='root';

Restart the mysql client

sudo service mysql restart
GangaRam Dewasi
  • 631
  • 7
  • 11
-1

It works for me by adding network_mode in docker-compose.yml

version: '3'
services:
  aservice:
    image: image:latest
    ports:
      - "8080:8080"
      - "8787:8787"
    # Allow docker to connect to localhost
    network_mode: "host"
sendon1982
  • 9,982
  • 61
  • 44
-3

locally I had MySQL running on port 3306 and MySQL container running on the same port 3306

You have to be sure that MySQL or whatever database service that you are using in your container is stopped in your local envirmint before connecting to it

In my case, I had MySQL running through Homebrew

brew services stop mysql
Moode Osman
  • 1,715
  • 18
  • 17