Has anyone deployed Metabase to Google Cloud Run?

I’m trying to deploy Metabase on Google Cloud Run backed by Postgres on Cloud SQL. However, I’m struggling to establish a connection from Metabase to Cloud SQL.

Apparently I can only connect to Cloud SQL via Unix socket. I’ve tried the following values for MB_DB_CONNECTION_URI, but it seems that Metabase completely ignores the setting and simply uses H2 instead:

postgres://user:pwd@/db?sslmode=disable&host=/cloudsql/instance:connection:name/
postgres://user:pwd@/db?sslmode=disable&host=/cloudsql/instance:connection:name/.s.PGSQL.5432
postgres://user:pwd@/db?sslmode=disable

Anyone else here had luck with this?

Hi @ismail
Is Run different than AppEngine, or is it just a name change?
Seems like others have been able to use Google Cloud AppEngine with success: Google Cloud AppEngine

Yes, it’s a different product entirely that lets you serve arbitrary containers. I believe App Engine requires you to use a Google-approved base image.

I think a major difference is that Cloud Run only supports connections to Cloud SQL via Unix socket. This does not seem to work though, likely because Cloud SQL sockets contain “:” characters that break the regex that reads “MB_DB_CONNECTION_URI”.

@ismail
Just for reference, so others can find the feature request, if they search the forum:
https://github.com/metabase/metabase/issues/11414
Have you tried %3A instead of colon?

@ismail Have you checked the example code?
https://github.com/GoogleCloudPlatform/java-docs-samples/tree/master/cloud-sql/postgres/servlet
https://github.com/GoogleCloudPlatform/java-docs-samples/blob/master/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/ConnectionPoolContextListener.java

That looks like you can make a string like this:
MB_DB_CONNECTION_URI="postgres://<MY-DB-USER>:<MY-DB-PASS>@/<MY-DB>?cloudSqlInstance='<MY-PROJECT>:<INSTANCE-REGION>:<MY-DATABASE>'&socketFactory=com.google.cloud.sql.mysql.SocketFactory

Alternatively try to use %3A instead of the : And try without the single-quote too.

EDIT:
It seems like Postgres JDBC (check the section “Unix sockets”) doesn’t support sockets, but maybe you could do a workaround with a TCP forward:
https://coderwall.com/p/c3wyzq/forwarding-tcp-traffic-to-a-unix-socket
Seems like it’s similar to what Google hints at:
https://cloud.google.com/sql/docs/postgres/connect-external-app

@flamber, thanks for suggestions. Some attempts:

Have you tried %3A instead of colon

Yes. I set MB_DB_CONNECTION_URL to postgres://user:pwd@/dbname?host=/cloudsql/project%3Aregion%3Aproject/, but Metabase seems to ignore this and reverts to H2 without throwing any exceptions.

That looks like you can make a string like this:
MB_DB_CONNECTION_URI="postgres://<MY-DB-USER>:<MY-DB-PASS>@/<MY-DB>?cloudSqlInstance='<MY-PROJECT>:<INSTANCE-REGION>:<MY-DATABASE>'&socketFactory=com.google.cloud.sql.mysql.SocketFactory

I think this works if you’ve included the relevant Google Cloud libraries in the jar itself, but I don’t know how to do that.

…but maybe you could do a workaround with a TCP forward

This worked for me, finally!

I made my own Dockerfile like this:

FROM metabase/metabase

RUN apk update
RUN apk add --no-cache socat

# Set up symlink to Cloud SQL UNIX socket
RUN ln -s /cloudsql/<instance-name-goes-here>/.s.PGSQL.5432 pg.sock

COPY startup.sh startup.sh
RUN chmod +x startup.sh
ENTRYPOINT ["./startup.sh"]

… where ./startup.sh looks like:

#! /bin/bash

# Forward TCP:5432 to Cloud SQL Unix socket
nohup socat -d -d TCP4-LISTEN:5432,fork UNIX-CONNECT:pg.sock &

# Runs Metabase
/app/run_metabase.sh

I still had to use a symlink because even socat can’t handle paths that contain :.

1 Like