Hello all,
I'm experiencing a persistent and critical issue with my Cloud Run service's integration with Cloud SQL, where the CLOUD_SQL_CONNECTION_NAME environment variable is not being set, leading to a "Connection refused" error in my application. I've thoroughly debugged this, but haven't found a resolution.
Here are the details of my setup and the troubleshooting steps I've already performed.
Problem Description:
My PHP application, deployed on Cloud Run, attempts to connect to Cloud SQL using 127.0.0.1:3306 as per the standard Cloud SQL Auth Proxy integration. However, the application consistently receives a SQLSTATE[HY000] [2002] Connection refused error. Furthermore, a debug print of all environment variables within the PHP code shows that the expected CLOUD_SQL_CONNECTION_NAME variable is missing.
Troubleshooting Steps Performed:
Given these comprehensive checks, it appears the issue is not with my configuration or application code, but rather a deeper problem with the Cloud Run platform's ability to provision and inject the Cloud SQL proxy and its associated environment variables within my project(s).
Can someone is able to confirm this bug/issue ?
How to solve it ?
Here my Dockerfile:
FROM php:8.1-apache
RUN apt-get update && \
apt-get install -y \
libmariadb-dev \
&& rm -rf /var/lib/apt/lists/*
RUN docker-php-ext-install pdo_mysql
COPY ./src/html /var/www/html
EXPOSE 80
And my php code:
<?php print_r(getenv()); ?>
Thank you in advance.
Solved! Go to Solution.
The docs page I referenced does not say that Cloud Run sets the INSTANCE_UNIX_SOCKET environment variable value for you, so I don't know where that idea came from!
From your reply I infer that you would like to connect to your Cloud SQL instance via its public IP address as this is the only option that makes use of Cloud SQL Auth Proxy, according to the docs.
Under such use case, a database instance that you add to the Cloud SQL connections section of the Cloud Run service configuration is going to get a UNIX socket file created for it, and the docs define the name of that file.
For example, my project dml-sandbox-pigeon has a Cloud SQL instance called mysql-srv in the us-central1 Google Cloud region. If I add my SQL instance to my Cloud Run service configuration, the following file will be created on the container's virtual filesystem when container starts:
/cloudsql/dml-sandbox-pigeon:us-central1:mysql-srv
My PHP application can communicate with the SQL instance through that UNIX domain socket.
Now, in that particular PHP code example from the docs page, they don't hardcode the UNIX domain socket name in the application code but read it from an environment variable, instead. Which means if you want to use that code as is, you would have to set that environment variable value yourself in your Cloud Run service configuration.
For my example, I added INSTANCE_UNIX_SOCKET environment variable definition to the Cloud Run service configuration.
Note, that the code snippet from the docs page also makes use of the environment variables DB_USER, DB_PASS, and DB_NAME so I also have to set those on the configuration form as well:
I also add the connection name of my SQL instance to the form:
With this set-up in place, the PHP code from the docs page should work, provided that other requirements are satisfied.
Warning:
Storing the username and password in environmental variables is not best practice and I've done so out of convenience only. Once you get your connection working, I recommend that you research the part of the docs page that talks about Secret Manager, and set up your service to read the username and password from Secret Manager.
The environment variable you mentioned is not set by the Cloud SQL connector in Cloud Run. Read this docs page carefully. It explains every possible connection scenario (with/without a public IP address) and, where PHP is supported, offers a code example as well.
Thank you for you answer !
I thought it was the case...
Nevertheless, I read and saw that connector should configure following environement variable:
INSTANCE_UNIX_SOCKET
Which is again not the case...
The docs page I referenced does not say that Cloud Run sets the INSTANCE_UNIX_SOCKET environment variable value for you, so I don't know where that idea came from!
From your reply I infer that you would like to connect to your Cloud SQL instance via its public IP address as this is the only option that makes use of Cloud SQL Auth Proxy, according to the docs.
Under such use case, a database instance that you add to the Cloud SQL connections section of the Cloud Run service configuration is going to get a UNIX socket file created for it, and the docs define the name of that file.
For example, my project dml-sandbox-pigeon has a Cloud SQL instance called mysql-srv in the us-central1 Google Cloud region. If I add my SQL instance to my Cloud Run service configuration, the following file will be created on the container's virtual filesystem when container starts:
/cloudsql/dml-sandbox-pigeon:us-central1:mysql-srv
My PHP application can communicate with the SQL instance through that UNIX domain socket.
Now, in that particular PHP code example from the docs page, they don't hardcode the UNIX domain socket name in the application code but read it from an environment variable, instead. Which means if you want to use that code as is, you would have to set that environment variable value yourself in your Cloud Run service configuration.
For my example, I added INSTANCE_UNIX_SOCKET environment variable definition to the Cloud Run service configuration.
Note, that the code snippet from the docs page also makes use of the environment variables DB_USER, DB_PASS, and DB_NAME so I also have to set those on the configuration form as well:
I also add the connection name of my SQL instance to the form:
With this set-up in place, the PHP code from the docs page should work, provided that other requirements are satisfied.
Warning:
Storing the username and password in environmental variables is not best practice and I've done so out of convenience only. Once you get your connection working, I recommend that you research the part of the docs page that talks about Secret Manager, and set up your service to read the username and password from Secret Manager.
Thank you, it was working 🙂
Here the code I used:
$dbName = getenv('DB_NAME');
$username = getenv('DB_USER');
$password = getenv('DB_PASS');
$dbHost = getenv('DB_HOST');
$dbPort = getenv('DB_PORT');
if (strpos($dbHost, '/')) {
// Connect using UNIX sockets
$dsn = sprintf(
'mysql:dbname=%s;unix_socket=%s',
$dbName,
$dbHost
);
} else {
// Connect using TCP/IP.
$dsn = sprintf(
'mysql:dbname=%s;host=%s;port=%s;',
$dbName,
$dbHost,
$dbPort
);
}
// Connect to the database.
$pdo = new PDO(
$dsn,
$username,
$password,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false,
]
);
I set the DB_HOST to my cloud SQL instance socket path:
/cloudsql/dml-sandbox-pigeon:us-central1:mysql-srv
KR.
Thank you Oliver, I thought it was the case.
Nevertheless, I checked and saw that connector is supposed to setup environement variable named "INSTANCE_UNIX_SOCKET".
But again, I don't have this variable. It's like connector is not up...