Connect from Cloud Build

MySQL  |  PostgreSQL  |  SQL Server

This page contains information and examples for connecting to aCloud SQL instance from a service running in Cloud Build.

Cloud SQL is a fully-managed database service that helps you set up, maintain, manage, and administer your relational databases in the cloud.

Cloud Build is a service that executes your builds on Google Cloud infrastructure.

Set up a Cloud SQL instance

  1. Enable the Cloud SQL Admin API in the Google Cloud project that you are connecting from, if you haven't already done so:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enable permission.Learn how to grant roles.

    Enable the API

  2. Create a Cloud SQL for SQL Server instance. We recommend that you choose a Cloud SQL instance location in the same region as your Cloud Run service for better latency, to avoid some networking costs, and to reduce cross region failure risks.

    By default, Cloud SQL assigns a public IP address to a new instance. You also have the option to assign a private IP address. For more information about the connectivity options for both, see the Connecting Overview page.

  3. When you create the instance, you can choose the server certificate (CA) hierarchy for the instance and then configure the hierarchy as theserverCaMode for the instance. You must select the per-instance CA option (GOOGLE_MANAGED_INTERNAL_CA) as the server CA mode for instances that you want to connect to from web applications.

Set up an Artifact Registry Repository

  1. If you haven't already done so, then enable the Artifact Registry API in the Google Cloud project that you are connecting from:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enable permission.Learn how to grant roles.

    Enable the API

  2. Create a Docker Artifact Registry. To improve latency, reduce the risk of cross-region failure, and avoid additional networking costs, we recommend that you choose an Artifact Registrylocation in the same region as your Cloud Run service.

Configure Cloud Build

The steps to configure Cloud Build depend on the type ofIP address that you assigned to your Cloud SQL instance.

Public IP (default)

Make sure your Cloud Build service account has theIAM roles and permissions required to connect to the Cloud SQL instance. The Cloud Build service account is listed on the Google Cloud consoleIAM page as thePrincipal[YOUR-PROJECT-NUMBER]@cloudbuild.gserviceaccount.com.

To view this service account in the Google Cloud console, select theInclude Google-provided role grants checkbox.

Your Cloud Build service account needs theCloud SQL ClientIAM role.

If the Cloud Build service account belongs to a different projectthan the Cloud SQL instance, then the Cloud SQL Admin API and the role need to be added for both projects.

Private IP

To connect to your Cloud SQL instance over private IP, Cloud Buildmust be in the same VPC network as your Cloud SQL instance. To configure this:

  1. Set up a private connection between theVPC network of your Cloud SQL instance and the service producer network.
  2. Create aCloud Build private pool.

Once configured, your application will be able to connect directly using yourinstance's private IP address and port1433 when your build is run in the pool.

Connect to Cloud SQL

After you configure Cloud Build, you can connect to yourCloud SQL instance.

Public IP (default)

For public IP paths, Cloud Build supports TCP sockets.

Connect with TCP

Python

To see this snippet in the context of a web application, viewthe README on GitHub.

importosimportsqlalchemydefconnect_tcp_socket()->sqlalchemy.engine.base.Engine:"""Initializes a TCP connection pool for a Cloud SQL instance of SQL Server."""# Note: Saving credentials in environment variables is convenient, but not# secure - consider a more secure solution such as# Cloud Secret Manager (https://cloud.google.com/secret-manager) to help# keep secrets safe.db_host=os.environ["INSTANCE_HOST"]# e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)db_user=os.environ["DB_USER"]# e.g. 'my-db-user'db_pass=os.environ["DB_PASS"]# e.g. 'my-db-password'db_name=os.environ["DB_NAME"]# e.g. 'my-database'db_port=os.environ["DB_PORT"]# e.g. 1433pool=sqlalchemy.create_engine(# Equivalent URL:# mssql+pytds://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>sqlalchemy.engine.url.URL.create(drivername="mssql+pytds",username=db_user,password=db_pass,database=db_name,host=db_host,port=db_port,),# ...)returnpool

Java

To see this snippet in the context of a web application, viewthe README on GitHub.

Note:

importcom.zaxxer.hikari.HikariConfig;importcom.zaxxer.hikari.HikariDataSource;importjavax.sql.DataSource;publicclassTcpConnectionPoolFactoryextendsConnectionPoolFactory{// Note: Saving credentials in environment variables is convenient, but not// secure - consider a more secure solution such as// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help// keep secrets safe.privatestaticfinalStringDB_USER=System.getenv("DB_USER");privatestaticfinalStringDB_PASS=System.getenv("DB_PASS");privatestaticfinalStringDB_NAME=System.getenv("DB_NAME");privatestaticfinalStringINSTANCE_HOST=System.getenv("INSTANCE_HOST");privatestaticfinalStringDB_PORT=System.getenv("DB_PORT");publicstaticDataSourcecreateConnectionPool(){// The configuration object specifies behaviors for the connection pool.HikariConfigconfig=newHikariConfig();// Configure which instance and what database user to connect with.config.setJdbcUrl(String.format("jdbc:sqlserver://%s:%s;databaseName=%s",INSTANCE_HOST,DB_PORT,DB_NAME));config.setUsername(DB_USER);// e.g. "root", "sqlserver"config.setPassword(DB_PASS);// e.g. "my-password"// ... Specify additional connection properties here.// ...// Initialize the connection pool using the configuration object.returnnewHikariDataSource(config);}}

Node.js

To see this snippet in the context of a web application, viewthe README on GitHub.

constmssql=require('mssql');// createTcpPool initializes a TCP connection pool for a Cloud SQL// instance of SQL Server.constcreateTcpPool=asyncconfig=>{// Note: Saving credentials in environment variables is convenient, but not// secure - consider a more secure solution such as// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help// keep secrets safe.constdbConfig={server:process.env.INSTANCE_HOST,// e.g. '127.0.0.1'port:parseInt(process.env.DB_PORT),// e.g. 1433user:process.env.DB_USER,// e.g. 'my-db-user'password:process.env.DB_PASS,// e.g. 'my-db-password'database:process.env.DB_NAME,// e.g. 'my-database'options:{trustServerCertificate:true,},// ... Specify additional properties here....config,};// Establish a connection to the database.returnmssql.connect(dbConfig);};

Go

To see this snippet in the context of a web application, viewthe README on GitHub.

packagecloudsqlimport("database/sql""fmt""log""os""strings"_"github.com/denisenkom/go-mssqldb")// connectTCPSocket initializes a TCP connection pool for a Cloud SQL// instance of SQL Server.funcconnectTCPSocket()(*sql.DB,error){mustGetenv:=func(kstring)string{v:=os.Getenv(k)ifv==""{log.Fatalf("Fatal Error in connect_tcp.go: %s environment variable not set.\n",k)}returnv}// Note: Saving credentials in environment variables is convenient, but not// secure - consider a more secure solution such as// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help// keep secrets safe.var(dbUser=mustGetenv("DB_USER")// e.g. 'my-db-user'dbPwd=mustGetenv("DB_PASS")// e.g. 'my-db-password'dbTCPHost=mustGetenv("INSTANCE_HOST")// e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)dbPort=mustGetenv("DB_PORT")// e.g. '1433'dbName=mustGetenv("DB_NAME")// e.g. 'my-database')dbURI:=fmt.Sprintf("server=%s;user id=%s;password=%s;port=%s;database=%s;",dbTCPHost,dbUser,dbPwd,dbPort,dbName)// dbPool is the pool of database connections.dbPool,err:=sql.Open("sqlserver",dbURI)iferr!=nil{returnnil,fmt.Errorf("sql.Open: %w",err)}// ...returndbPool,nil}

C#

To see this snippet in the context of a web application, viewthe README on GitHub.

usingMicrosoft.Data.SqlClient;usingSystem;namespaceCloudSql{publicclassSqlServerTcp{publicstaticSqlConnectionStringBuilderNewSqlServerTCPConnectionString(){// Equivalent connection string:// "User Id=<DB_USER>;Password=<DB_PASS>;Server=<INSTANCE_HOST>;Database=<DB_NAME>;"varconnectionString=newSqlConnectionStringBuilder(){// Note: Saving credentials in environment variables is convenient, but not// secure - consider a more secure solution such as// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help// keep secrets safe.DataSource=Environment.GetEnvironmentVariable("INSTANCE_HOST"),// e.g. '127.0.0.1'// Set Host to 'cloudsql' when deploying to App Engine Flexible environmentUserID=Environment.GetEnvironmentVariable("DB_USER"),// e.g. 'my-db-user'Password=Environment.GetEnvironmentVariable("DB_PASS"),// e.g. 'my-db-password'InitialCatalog=Environment.GetEnvironmentVariable("DB_NAME"),// e.g. 'my-database'// The Cloud SQL proxy provides encryption between the proxy and instanceEncrypt=false,};connectionString.Pooling=true;// Specify additional properties here.returnconnectionString;}}}

Ruby

To see this snippet in the context of a web application, viewthe README on GitHub.

tcp:&tcpadapter:sqlserver# Configure additional properties here.# Note: Saving credentials in environment variables is convenient, but not# secure - consider a more secure solution such as# Cloud Secret Manager (https://cloud.google.com/secret-manager) to help# keep secrets safe.username:<%= ENV["DB_USER"] %>  # e.g. "my-database-user"  password: <%=ENV["DB_PASS"]%># e.g. "my-database-password"database:<%= ENV.fetch("DB_NAME") { "vote_development" } %>  host: <%=ENV.fetch("INSTANCE_HOST"){"127.0.0.1"}%># '172.17.0.1' if deployed to GAE Flexport:<%=ENV.fetch("DB_PORT"){1433}%>

PHP

To see this snippet in the context of a web application, viewthe README on GitHub.

namespace Google\Cloud\Samples\CloudSQL\SQLServer;use PDO;use PDOException;use RuntimeException;use TypeError;class DatabaseTcp{    public static function initTcpDatabaseConnection(): PDO    {        try {            // Note: Saving credentials in environment variables is convenient, but not            // secure - consider a more secure solution such as            // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help            // keep secrets safe.            $username = getenv('DB_USER'); // e.g. 'your_db_user'            $password = getenv('DB_PASS'); // e.g. 'your_db_password'            $dbName = getenv('DB_NAME'); // e.g. 'your_db_name'            $instanceHost = getenv('INSTANCE_HOST'); // e.g. '127.0.0.1' ('172.17.0.1' for GAE Flex)            // Connect using TCP            $dsn = sprintf(                'sqlsrv:server=%s;Database=%s',                $instanceHost,                $dbName            );            // Connect to the database            $conn = new PDO(                $dsn,                $username,                $password,                # ...            );        } catch (TypeError $e) {            throw new RuntimeException(                sprintf(                    'Invalid or missing configuration! Make sure you have set ' .                        '$username, $password, $dbName, and $instanceHost (for TCP mode). ' .                        'The PHP error was %s',                    $e->getMessage()                ),                $e->getCode(),                $e            );        } catch (PDOException $e) {            throw new RuntimeException(                sprintf(                    'Could not connect to the Cloud SQL Database. Check that ' .                        'your username and password are correct, that the Cloud SQL ' .                        'proxy is running, and that the database exists and is ready ' .                        'for use. For more assistance, refer to %s. The PDO error was %s',                    'https://cloud.google.com/sql/docs/sqlserver/connect-external-app',                    $e->getMessage()                ),                (int) $e->getCode(),                $e            );        }        return $conn;    }}

You can use the Cloud SQL Auth Proxy in a Cloud Build step to allow connections to your database.This configuration:

  1. Builds your container and pushes it to Artifact Registry.
  2. Builds a second container, copying in the Cloud SQL Auth Proxy binary.
  3. Using the second container, starts the Cloud SQL Auth Proxy and runs any migration commands.
steps:-id:install-proxyname:gcr.io/cloud-builders/wgetentrypoint:shargs:--c-|wget-O/workspace/cloud-sql-proxyhttps://storage.googleapis.com/cloud-sql-connectors/cloud-sql-proxy/2.20.0chmod+x/workspace/cloud-sql-proxy-id:migratewaitFor:['install-proxy']name:YOUR_CONTAINER_IMAGE_NAMEentrypoint:shenv:-"DATABASE_NAME=${_DATABASE_NAME}"-"DATABASE_USER=${_DATABASE_USER}"-"DATABASE_PORT=${_DATABASE_PORT}"-"INSTANCE_CONNECTION_NAME=${_INSTANCE_CONNECTION_NAME}"secretEnv:-DATABASE_PASSargs:-"-c"-|/workspace/cloud-sql-proxy${_INSTANCE_CONNECTION_NAME}--port${_DATABASE_PORT}&sleep2;# Cloud SQL Proxy is now up and running, add your own logic below to connectpythonmigrate.py# For exampleoptions:dynamic_substitutions:truesubstitutions:_DATABASE_USER:myuser_DATABASE_NAME:mydatabase_INSTANCE_CONNECTION_NAME:${PROJECT_ID}:us-central1:myinstance_DATABASE_PORT:1433_DATABASE_PASSWORD_KEY:database_password_AR_REPO_REGION:us-central1_AR_REPO_NAME:my-docker-repo_IMAGE_NAME:${_AR_REPO_REGION}-docker.pkg.dev/${PROJECT_ID}/${_AR_REPO_NAME}/sample-sql-proxyavailableSecrets:secretManager:-versionName:projects/$PROJECT_ID/secrets/${_DATABASE_PASSWORD_KEY}/versions/latestenv:"DATABASE_PASS"

The Cloud Build code sample shows how you might run a hypotheticalmigrate.py script after deploying the previous sample app to update its Cloud SQL database using the Cloud SQL Auth Proxy and Cloud Build. To run this Cloud Build code sample the setup steps required are:

  1. Create a folder namesql-proxy
  2. Create aDockerfile file in thesql-proxy folder with the following single line of code for its file contents:
    FROMgcr.io/gcp-runtimes/ubuntu_20_0_4
  3. Create acloudbuild.yaml file in thesql-proxy folder.
  4. Update thecloudbuild.yaml file:
    1. Copy the previous sample Cloud Build code and paste it into thecloudbuild.yaml file.
    2. Update the example code_DATABASE_PORT within thesubstitutions: block to be1433, which is the port used by SQL Server.
    3. Replace the following placeholder values with the values used in your project:
      • mydatabase
      • myuser
      • myinstance
  5. Create a secret nameddatabase_password inSecret Manager.
  6. Create amigrate.py script file in thesql-proxy folder.
    • The script can reference the following environment variables and the secret created in thecloudbuild.yaml file using the following examples:
      • os.getenv('DATABASE_NAME')
      • os.getenv('DATABASE_USER')
      • os.getenv('DATABASE_PASS')
      • os.getenv('INSTANCE_CONNECTION_NAME')
    • To reference the same variables from a Bash script (for example:migrate.sh) use the following examples:
      • $DATABASE_NAME
      • $DATABASE_USER
      • $DATABASE_PASS
      • $INSTANCE_CONNECTION_NAME
  7. Run the followinggcloud builds submit command to build a container with the Cloud SQL Auth Proxy, start the Cloud SQL Auth Proxy, and run themigrate.py script:
    gcloudbuildssubmit--configcloudbuild.yaml

Private IP

For private IP paths, your application connects directly to yourinstance through private pools.This method uses TCP to connect directly to the Cloud SQLinstance without using the Cloud SQL Auth Proxy.

Connect with TCP

Connect using the private IP address of your Cloud SQL instance as the host and port1433.

Python

To see this snippet in the context of a web application, viewthe README on GitHub.

importosimportsqlalchemydefconnect_tcp_socket()->sqlalchemy.engine.base.Engine:"""Initializes a TCP connection pool for a Cloud SQL instance of SQL Server."""# Note: Saving credentials in environment variables is convenient, but not# secure - consider a more secure solution such as# Cloud Secret Manager (https://cloud.google.com/secret-manager) to help# keep secrets safe.db_host=os.environ["INSTANCE_HOST"]# e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)db_user=os.environ["DB_USER"]# e.g. 'my-db-user'db_pass=os.environ["DB_PASS"]# e.g. 'my-db-password'db_name=os.environ["DB_NAME"]# e.g. 'my-database'db_port=os.environ["DB_PORT"]# e.g. 1433pool=sqlalchemy.create_engine(# Equivalent URL:# mssql+pytds://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>sqlalchemy.engine.url.URL.create(drivername="mssql+pytds",username=db_user,password=db_pass,database=db_name,host=db_host,port=db_port,),# ...)returnpool

Java

To see this snippet in the context of a web application, viewthe README on GitHub.

Note:

importcom.zaxxer.hikari.HikariConfig;importcom.zaxxer.hikari.HikariDataSource;importjavax.sql.DataSource;publicclassTcpConnectionPoolFactoryextendsConnectionPoolFactory{// Note: Saving credentials in environment variables is convenient, but not// secure - consider a more secure solution such as// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help// keep secrets safe.privatestaticfinalStringDB_USER=System.getenv("DB_USER");privatestaticfinalStringDB_PASS=System.getenv("DB_PASS");privatestaticfinalStringDB_NAME=System.getenv("DB_NAME");privatestaticfinalStringINSTANCE_HOST=System.getenv("INSTANCE_HOST");privatestaticfinalStringDB_PORT=System.getenv("DB_PORT");publicstaticDataSourcecreateConnectionPool(){// The configuration object specifies behaviors for the connection pool.HikariConfigconfig=newHikariConfig();// Configure which instance and what database user to connect with.config.setJdbcUrl(String.format("jdbc:sqlserver://%s:%s;databaseName=%s",INSTANCE_HOST,DB_PORT,DB_NAME));config.setUsername(DB_USER);// e.g. "root", "sqlserver"config.setPassword(DB_PASS);// e.g. "my-password"// ... Specify additional connection properties here.// ...// Initialize the connection pool using the configuration object.returnnewHikariDataSource(config);}}

Node.js

To see this snippet in the context of a web application, viewthe README on GitHub.

constmssql=require('mssql');// createTcpPool initializes a TCP connection pool for a Cloud SQL// instance of SQL Server.constcreateTcpPool=asyncconfig=>{// Note: Saving credentials in environment variables is convenient, but not// secure - consider a more secure solution such as// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help// keep secrets safe.constdbConfig={server:process.env.INSTANCE_HOST,// e.g. '127.0.0.1'port:parseInt(process.env.DB_PORT),// e.g. 1433user:process.env.DB_USER,// e.g. 'my-db-user'password:process.env.DB_PASS,// e.g. 'my-db-password'database:process.env.DB_NAME,// e.g. 'my-database'options:{trustServerCertificate:true,},// ... Specify additional properties here....config,};// Establish a connection to the database.returnmssql.connect(dbConfig);};

Go

To see this snippet in the context of a web application, viewthe README on GitHub.

packagecloudsqlimport("database/sql""fmt""log""os""strings"_"github.com/denisenkom/go-mssqldb")// connectTCPSocket initializes a TCP connection pool for a Cloud SQL// instance of SQL Server.funcconnectTCPSocket()(*sql.DB,error){mustGetenv:=func(kstring)string{v:=os.Getenv(k)ifv==""{log.Fatalf("Fatal Error in connect_tcp.go: %s environment variable not set.\n",k)}returnv}// Note: Saving credentials in environment variables is convenient, but not// secure - consider a more secure solution such as// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help// keep secrets safe.var(dbUser=mustGetenv("DB_USER")// e.g. 'my-db-user'dbPwd=mustGetenv("DB_PASS")// e.g. 'my-db-password'dbTCPHost=mustGetenv("INSTANCE_HOST")// e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)dbPort=mustGetenv("DB_PORT")// e.g. '1433'dbName=mustGetenv("DB_NAME")// e.g. 'my-database')dbURI:=fmt.Sprintf("server=%s;user id=%s;password=%s;port=%s;database=%s;",dbTCPHost,dbUser,dbPwd,dbPort,dbName)// dbPool is the pool of database connections.dbPool,err:=sql.Open("sqlserver",dbURI)iferr!=nil{returnnil,fmt.Errorf("sql.Open: %w",err)}// ...returndbPool,nil}

C#

To see this snippet in the context of a web application, viewthe README on GitHub.

usingMicrosoft.Data.SqlClient;usingSystem;namespaceCloudSql{publicclassSqlServerTcp{publicstaticSqlConnectionStringBuilderNewSqlServerTCPConnectionString(){// Equivalent connection string:// "User Id=<DB_USER>;Password=<DB_PASS>;Server=<INSTANCE_HOST>;Database=<DB_NAME>;"varconnectionString=newSqlConnectionStringBuilder(){// Note: Saving credentials in environment variables is convenient, but not// secure - consider a more secure solution such as// Cloud Secret Manager (https://cloud.google.com/secret-manager) to help// keep secrets safe.DataSource=Environment.GetEnvironmentVariable("INSTANCE_HOST"),// e.g. '127.0.0.1'// Set Host to 'cloudsql' when deploying to App Engine Flexible environmentUserID=Environment.GetEnvironmentVariable("DB_USER"),// e.g. 'my-db-user'Password=Environment.GetEnvironmentVariable("DB_PASS"),// e.g. 'my-db-password'InitialCatalog=Environment.GetEnvironmentVariable("DB_NAME"),// e.g. 'my-database'// The Cloud SQL proxy provides encryption between the proxy and instanceEncrypt=false,};connectionString.Pooling=true;// Specify additional properties here.returnconnectionString;}}}

Ruby

To see this snippet in the context of a web application, viewthe README on GitHub.

tcp:&tcpadapter:sqlserver# Configure additional properties here.# Note: Saving credentials in environment variables is convenient, but not# secure - consider a more secure solution such as# Cloud Secret Manager (https://cloud.google.com/secret-manager) to help# keep secrets safe.username:<%= ENV["DB_USER"] %>  # e.g. "my-database-user"  password: <%=ENV["DB_PASS"]%># e.g. "my-database-password"database:<%= ENV.fetch("DB_NAME") { "vote_development" } %>  host: <%=ENV.fetch("INSTANCE_HOST"){"127.0.0.1"}%># '172.17.0.1' if deployed to GAE Flexport:<%=ENV.fetch("DB_PORT"){1433}%>

PHP

To see this snippet in the context of a web application, viewthe README on GitHub.

namespace Google\Cloud\Samples\CloudSQL\SQLServer;use PDO;use PDOException;use RuntimeException;use TypeError;class DatabaseTcp{    public static function initTcpDatabaseConnection(): PDO    {        try {            // Note: Saving credentials in environment variables is convenient, but not            // secure - consider a more secure solution such as            // Cloud Secret Manager (https://cloud.google.com/secret-manager) to help            // keep secrets safe.            $username = getenv('DB_USER'); // e.g. 'your_db_user'            $password = getenv('DB_PASS'); // e.g. 'your_db_password'            $dbName = getenv('DB_NAME'); // e.g. 'your_db_name'            $instanceHost = getenv('INSTANCE_HOST'); // e.g. '127.0.0.1' ('172.17.0.1' for GAE Flex)            // Connect using TCP            $dsn = sprintf(                'sqlsrv:server=%s;Database=%s',                $instanceHost,                $dbName            );            // Connect to the database            $conn = new PDO(                $dsn,                $username,                $password,                # ...            );        } catch (TypeError $e) {            throw new RuntimeException(                sprintf(                    'Invalid or missing configuration! Make sure you have set ' .                        '$username, $password, $dbName, and $instanceHost (for TCP mode). ' .                        'The PHP error was %s',                    $e->getMessage()                ),                $e->getCode(),                $e            );        } catch (PDOException $e) {            throw new RuntimeException(                sprintf(                    'Could not connect to the Cloud SQL Database. Check that ' .                        'your username and password are correct, that the Cloud SQL ' .                        'proxy is running, and that the database exists and is ready ' .                        'for use. For more assistance, refer to %s. The PDO error was %s',                    'https://cloud.google.com/sql/docs/sqlserver/connect-external-app',                    $e->getMessage()                ),                (int) $e->getCode(),                $e            );        }        return $conn;    }}

You can then create a Cloud Build step to run your code directly.

steps:-id:"docker-build"name:"gcr.io/cloud-builders/docker"args:["build","-t","${_IMAGE_NAME}","sql-private-pool/."]-id:"docker-push"name:"gcr.io/cloud-builders/docker"args:["push","${_IMAGE_NAME}"]-id:"migration"name:"${_IMAGE_NAME}"dir:sql-private-poolenv:-"DATABASE_NAME=mydatabase"-"DATABASE_USER=myuser"-"DATABASE_HOST=${_DATABASE_HOST}"-"DATABASE_TYPE=${_DATABASE_TYPE}"secretEnv:-DATABASE_PASSentrypoint:python# for exampleargs:["migrate.py"]# for exampleoptions:pool:name:projects/$PROJECT_ID/locations/us-central1/workerPools/private-pooldynamicSubstitutions:truesubstitutions:_DATABASE_PASSWORD_KEY:database_password_DATABASE_TYPE:postgres_AR_REPO_REGION:us-central1_AR_REPO_NAME:my-docker-repo_IMAGE_NAME:${_AR_REPO_REGION}-docker.pkg.dev/${PROJECT_ID}/${_AR_REPO_NAME}/sample-private-poolavailableSecrets:secretManager:-versionName:projects/$PROJECT_ID/secrets/${_DATABASE_PASSWORD_KEY}/versions/latestenv:DATABASE_PASS

The Cloud Build code sample above shows how you might run a hypotheticalmigrate script after deploying the sample app above to update its Cloud SQL database using Cloud Build. To run this Cloud Build code sample the setup steps required are:

  1. Create a folder namesql-private-pool
  2. Create aDockerfile file in thesql-private-pool folder with the following single line of code for its file contents:

    FROM gcr.io/gcp-runtimes/ubuntu_20_0_4

  3. Create acloudbuild.yaml file in thesql-private-pool folder.
  4. Update thecloudbuild.yaml file:
    1. Copy the sample Cloud Build code above and paste it into thecloudbuild.yaml file.
    2. Replace the following placeholder values with the values used in your project:
      • mydatabase
      • myuser
      • databasehost, in the formhost:port.
  5. Create a secret nameddatabase_password inSecret Manager.
  6. Create amigrate.py script file in thesql-proxy folder.
    • The script can reference the following environment variables and the secret created in thecloudbuild.yaml file using the following examples:
      • os.getenv('DATABASE_NAME')
      • os.getenv('DATABASE_USER')
      • os.getenv('DATABASE_PASS')
      • os.getenv('DATABASE_HOST')
    • To reference the same variables from a Bash script (for example:migrate.sh) use the following examples:
      • $DATABASE_NAME
      • $DATABASE_USER
      • $DATABASE_PASS
      • $DATABASE_HOST
  7. Run the followinggcloud builds submit command to build a container with the Cloud SQL Auth Proxy, start the Cloud SQL Auth Proxy, and run themigrate.py script:

    gcloud builds submit --config cloudbuild.yaml

Best practices and other information

You can use theCloud SQL Auth Proxy when testingyour application locally. See thequickstart for using the Cloud SQL Auth Proxyfor detailed instructions.

You can also test using theCloud SQL Proxy via a docker container.

Database schema migrations

By configuring Cloud Build to connect to Cloud SQL, you can run database schemamigration tasks in Cloud Build using the same code you would deploy to any other serverlessplatform.

Using Secret Manager

You can useSecret Manager to include sensitive information in your builds.

Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025-12-15 UTC.