9

I have Mysql Community Server installed on my mac, it is set up and is working, I can connect to it on localhost:3306 using Navicat for MySQL. However, whenever I try and connect to the database from my go app which is running using docker-compose, I get the following error:

dial tcp 127.0.0.1:3306: connect: connection refused

This is my go code:

// dbUser, dbPassword, & dbName are all variables that definitely contain the correct values
db, err = sql.Open("mysql", dbUser+":"+dbPassword+"@tcp(localhost:3306)/"+dbName)

if err != nil {
    panic(err.Error())
}

defer db.Close()

query, err := db.Query("INSERT INTO test_table(test_field) VALUES(This is a test)")

if err != nil {
    panic(err.Error())
}

defer query.Close()

and I am importing:

"database/sql"
_ "github.com/go-sql-driver/mysql"

Any help would be really appreciated, thank you.

william205
  • 678
  • 1
  • 7
  • 20
  • https://stackoverflow.com/questions/19712307/mysql-localhost-127-0-0-1 – kosa Sep 25 '18 at 18:09
  • This has been asked and answered before. Check [connecting from docker VM to host.](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach?answertab=active#tab-top) – Jacob Sep 25 '18 at 18:18

5 Answers5

13

You can't connect to localhost from Docker (especially on a Mac, where Docker runs in a Linux VM under the surface) and expect to access the services provided by the host machine.

However, there is functionality to access the host machine by IP address using the special hostname docker.for.mac.localhost. Absent any other Docker networking issues, amending your connection string to use docker.for.mac.localhost:3306 should resolve this issue and permit access to services on the host machine.

(More details about this workaround available in the Docker docs.)

Cosmic Ossifrage
  • 4,977
  • 29
  • 30
  • This works, thank you :) And thank you for the explanation. I am guessing because this is a workaround that I shouldn't be doing it this way, what is the proper way to develop with MySQL using docker-compose? (I am very new to docker) – william205 Sep 25 '18 at 18:17
  • 2
    There's nothing inherently wrong with this approach. It has the benefit that your database data persists – i.e. the data won't go away if you destroy a MySQL container accidentally, nor do you have to worry about mapping a host volume into such a container, which is more complex. The alternative would be to host a MySQL instance in Docker and set this up using Docker Compose in the same way. You gain Docker's internal container-to-container networking capabilities at this point. The main benefit of `docker.for.mac.localhost` is the Docker daemon will map that name to the host IP automatically. – Cosmic Ossifrage Sep 25 '18 at 18:27
  • Thank you for this, I really appreciate it :) – william205 Sep 25 '18 at 20:14
9

You should open like this:

db, err := sql.Open("mysql", "root:root@tcp(mysql:3306)/GoLife")

mysql is docker-compose service name.

Vitah
  • 97
  • 1
1

My solution ended up being a combination of the answers on this page. I was receiving the error:

dial tcp 127.0.0.1:3306: connect: connection refused

And my connection was constructed like so:

db, err := sql.Open("mysql",  "root:password@/mydbname?parseTime=true")

I read what @Cosmic Ossifrage had wasn't sure how to implement it so i applied the answer given by Vitah. this did not work because mysql:3306 was not a location that docker understood so connection failed. I then applied @Cosmic Ossifrage's solution with Vitah's to get a working setup.

db, err:= sql.Open("mysql", "root:password@tcp(docker.for.mac.localhost:3306)/mydbname?parseTime=true")

Hope this helps anyone searching for the answer! Thank you to the other contributors for helping me piece it together

Jake Boomgaarden
  • 3,394
  • 1
  • 17
  • 31
0

i used my local machine ip address to fix the issue , this is to connect to my mysql server running on my local from a docker-compose

Hashir Labs
  • 190
  • 2
  • 6
0

I think the best way to handle this is using the docker iptables.

If your docker-composer.yml

version: '3.9'
services:
    api:
        container_name: webapi
        restart: on-failure
        depends_on:
            - mariadb
        ...
   db:
        image: mariadb
        container_name: mariadb
        volumes:
            - database:/var/lib/mysql
        ports:
            - 3306:3306
        ...

You can use the container_name of the db service like this.

func main() {
  dsn := "user:pass@tcp(mariadb)/dbname?charset=utf8"
  db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

  if err != nil {
    panic(err.Error())
  }
}

Super easy, this is recommend if you db service has a dynamic IP.

Teocci
  • 7,189
  • 1
  • 50
  • 48