Search code examples
node.jsgoogle-cloud-platformgoogle-cloud-sqlgoogle-cloud-run

Connecting to Cloud SQL mySQL with Cloud run


I'm running a discord bot on cloud run (not ideal, but the cloud build is a lot quicker and the management is much cheaper) and I'm looking to connect it to a cloud mySQL database on a public IP. Been getting a lot of errors specifically ETIMEDOUT when trying to both make a connection pool and use that connection pool.

It is being deployed via the creation of a dockerfile in my build script, don't know if that matters at all.

function createConnectionPoolCloud(){
  const dboptions = {
    connectionLimit : 10,
    socketPath: process.env.INSTANCE_UNIX_SOCKET,
    user     : process.env.DB_USER,
    password : process.env.DB_PASS,
    database : process.env.DB_NAME,
    waitForConnections: true,
    connectTimeout: 5000
  }
  return mysql.createPool(dboptions);
};

That's the code I'm using, and I'm using the msql2 library.

I've connected the cloud sql instance to my cloud run deployment and have the cloud sql admin, & client roles on the service account. I have tested the sql connection with my local machine and that's working. I've played with the timeout a bit but it times out no matter the duration essentially. I've also ensured the unix socket is correct /cloudsql/instanceconnectionname.

I've followed these instructions as well and I have the cloud sql, run, & sql admin apis set up.

Don't know what exactly is causing this, I get the error as soon as I make the pool with the function and do a pool.promise() and then a promisePool.query(). Looked at some other posts and none of the solutions seemed to work out. On my local machine I am logging the entire pool object just to ensure I can see something but that doesn't appear at all in the cloud logs, it may just be the nature of logging a whole object but something worth mentioning.


Solution

  • I followed the same instructions and it works for me.

    const mysql = require('mysql2/promise');
    
    const dboptions = {
      socketPath: '/cloudsql/<PROJECT_ID>:<REGION>:<INSTANCE_NAME>',
      user: 'root',
      password: 'my-password',
      database: 'my-database',
      waitForConnections: true,
      connectTimeout: 5000
    }
    const pool = await mysql.createPool(dboptions);
    const [result] = await pool.query( `SELECT NOW();`);
    console.table(result); // prints returned time value from server
    

    You should consider using the Node.js Connector as it will handle the managing of certificates and mTLS connection for you. Also it doesn't require attaching the "Cloud SQL Connection".

    Here is how to start a new mysql2 connection pool.

    import mysql from 'mysql2/promise';
    import {Connector} from '@google-cloud/cloud-sql-connector';
    
    const connector = new Connector();
    const clientOpts = await connector.getOptions({
      instanceConnectionName: 'my-project:region:my-instance',
      ipType: 'PUBLIC',
    });
    const pool = await mysql.createPool({
      ...clientOpts,
      user: 'my-user',
      password: 'my-password',
      database: 'db-name',
    });
    const conn = await pool.getConnection();
    const [result] = await conn.query( `SELECT NOW();`);
    console.table(result); // prints returned time value from server
    
    await pool.end();
    connector.close();
    

    More information at https://github.com/GoogleCloudPlatform/cloud-sql-nodejs-connector#using-with-mysql