Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Cloud SQL proxy with Docker throws connection refused

I am trying to connect an application (docker container) to a Google Cloud SQL database using a cloudsql-proxy docker container. Therefore, I've created a docker-compose file with the following cloudsql-proxy container: (XXX replaced with my cloud sql instance id)

version: "3"

volumes:
  sqlproxy:

services:

  cloudsql-proxy:
    container_name: cloudsql-proxy
    image: gcr.io/cloudsql-docker/gce-proxy:1.11
    command: /cloud_sql_proxy --dir=/cloudsql -instances=XXX=tcp:0.0.0.0:3306 -credential_file=/config/credentials.json
    ports:
      - "3306:3306"
    volumes:
      - /usr/share/service-accounts/cloudsql-client.json:/config/credentials.json
      - sqlproxy:/cloudsql
      - /etc/ssl/certs:/etc/ssl/certs
    restart: always

Whenever I try to connect to the cloudsql mysql database from within another container running on the same machine, e.g. a second container within the docker-compose file, I get the error

"ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1' (111 "Connection refused")"

I tried to connect to the cloudsql-proxy with three different approaches, but still the same error. All containers (cloud sql proxy and test container to connect) are on one single google compute engine instance:

a) mysql-client: mysql --host 127.0.0.1

b) jdbc url: jdbc:mysql://127.0.0.1:3306/test

c) jdbc url: jdbc:mysql://cloudsql-proxy:3306/test

Within my gc firewall, I opened port 3306 for 0.0.0.0/0 for testing purposes, stopped and startet the cloud sql instance etc. but the error remains. The logs of the proxy container are OK:

2018/05/02 16:02:03 using credential file for authentication; [email protected]
2018/05/02 16:02:03 Listening on 0.0.0.0:3306 for x:x:x
2018/05/02 16:02:03 Ready for new connections

Is there something fundamental wrong with my approach or did I miss something? Might this be a docker problem? I can ping the proxy container from other containers.

like image 403
pbeck Avatar asked Nov 08 '22 07:11

pbeck


1 Answers

This is not a Docker issue and changing the Google Cloud firewall would allow machines on the Internet to connect to port 3306 on the instance.

Figure 1
+--------------------------------------------+
| GCE instance                               |
|                                            |
| +-----------------+    +-----------------+ |
| |MySQL   127.0.0.1|    |Test    127.0.0.1| |
| |                 |    |                 | |
| +------3306-------+    +-----------------+ |
|         |                                  |
|         |                                  |
+--------3306--------------------------------+

The first figure shows that the container Test cannot reach the container MySQL as it is only aware of itself (127.0.0.1 on the loopback network). The error you are mentionning happens because MySQL is not running on port 3306 on the container Test.

An option to reach the container MySQL from Test is to add an overlay network.

# I recommend using the latest version
version: "3.6"

volumes:
  sqlproxy:

networks:
  mysql_net:
    driver: overlay

services:
  cloudsql-proxy:
    ...
    # This is not required
    # ports:
    #   - "3306:3306"
    ...
    networks:
      mysql_net:
        aliases:
          database

  test-container:
    # Reach the container MySQL using the alias
    command: mysql -u <user> -p --host database
    ...
    networks:
      mysql_net:

As the second figure shows, the two containers now share a common subnetwork. The container Test should be able to reach the container MySQL.

Figure 2
+-----------------------------------------------------------+
| GCE instance                                              |
|                                                           |
| +-------------------------------+   +-------------------+ |
|  MySQL     127.0.0.1            |   |Test     127.0.0.1 | |
| |          10.0.0.3/8 (database)|   |         10.0.0.4/8| |
| |                               |   |                   | |
| |                               |   |                   | |
| +------------3306---------------+   +-------------------+ |
|                                                           |
+-----------------------------------------------------------+

As the IP of the container is unknown, you have to use an alias (like a domain name). In the example, the alias is database. The second figure assumes that the overlay network mysql_net has mask 255.0.0.0 and the given IPs to the containers MySQL and Test are respectively 10.0.0.3 and 10.0.0.4.

like image 175
ealain Avatar answered Nov 14 '22 23:11

ealain