Cloud Run から Cloud SQL への接続

このページには、Cloud Run で実行しているサービスから Cloud SQL インスタンスに接続するための情報と例が含まれています。

Cloud SQL は、クラウド内のリレーショナル データベースの設定、維持、管理に役立つフルマネージド データベース サービスです。

Cloud SQL インスタンスの設定

  1. 接続元のプロジェクトで Cloud SQL API を有効にします(まだ有効にしていない場合)。

    API を有効にする

  2. Cloud SQL for PostgreSQL のインスタンスを作成します

    Cloud SQL は、デフォルトで新しいインスタンスにパブリック IP アドレスを割り当てます。プライベート IP アドレスを割り当てることもできます。両方の接続オプションの詳細については、接続の概要ページをご覧ください。

Cloud Run の構成

Cloud Run を構成する手順は、Cloud SQL インスタンスに割り振った IP アドレスのタイプによって異なります。すべての下り(外向き)トラフィックを VPC コネクタ経由でルーティングする場合、プライベート IP を使用する必要があります。

パブリック IP(デフォルト)

  • 作成したインスタンスにパブリック IP アドレスがあることを確認します。これは、Google Cloud Console のインスタンスの [概要] ページで確認できます。パブリック IP を追加する必要がある場合は、パブリック IP の構成ページの手順をご覧ください。
  • インスタンスの CLOUD_SQL_CONNECTION_NAME を取得します。これは、Google Cloud Console のインスタンスの [概要] ページで確認できます。また、コマンド gcloud sql instances describe INSTANCE_NAME を実行して確認することもできます。
  • サービスのサービス アカウントを構成します。サービス アカウントに適切な Cloud SQL のロールと Cloud SQL への接続権限があることを確認してください。
      お使いのサービスのサービス アカウントには、次のいずれかの IAM ロールが必要です。
      • Cloud SQL Client(推奨)
      • Cloud SQL Admin
      または、次の IAM 権限を手動で割り当てることもできます。
      • cloudsql.instances.connect
      • cloudsql.instances.get

    サービス アカウントの承認が Cloud SQL インスタンスとは異なるプロジェクトに属している場合、Cloud SQL Admin API と IAM の権限を両方のプロジェクトに追加する必要があります。

他の構成変更の場合と同様に、Cloud SQL 接続に新しい構成を設定すると、新しい Cloud Run リビジョンが作成されます。明示的に更新しない限り、以降のリビジョンでも、この Cloud SQL 接続が自動的に設定されます。

Console

  1. Cloud Run に移動します

  2. サービスを構成します。

    • Cloud SQL 接続を新しいサービスに追加する場合:
      • サービスをコンテナ化して Container Registry にアップロードする必要があります。コンテナ イメージがまだない場合は、コンテナ イメージのビルドとデプロイに関する説明をご覧ください。
      • [サービスを作成] をクリックします。

    • Cloud SQL 接続を既存のサービスに追加する場合:
      • サービス名をクリックします。
      • [接続] タブをクリックします。
      • [デプロイ] をクリックします。
  3. Cloud SQL インスタンスへの接続を有効にします。
    • [詳細設定] をクリックします。
    • [接続] タブをクリックします。

    Cloud SQL 接続を追加する

    • プロジェクト内の Cloud SQL インスタンスへの接続を追加する場合は、プルダウン メニューから目的の Cloud SQL インスタンスを選択します。
    • 別のプロジェクトの Cloud SQL インスタンスを使用している場合は、プルダウンでカスタムの接続文字列を選択し、完全なインスタンス接続名を PROJECT-ID:REGION:INSTANCE-ID の形式で入力します。
    • 接続を削除する場合は、接続の右側にカーソルを置くと表示されるゴミ箱のアイコンをクリックします。
  4. [作成] または [デプロイ] をクリックします。

コマンドライン

後述のコマンドを使用する前に、次のように置き換えます。

  • IMAGE は、デプロイするイメージに置き換えます。
  • SERVICE_NAME は、Cloud Run サービスの名前に置き換えます。
  • CLOUD_SQL_CONNECTION_NAME は、Cloud SQL インスタンスのインスタンス接続名、または接続名のカンマ区切りのリストに置き換えます。

    新しいコンテナをデプロイする場合は、次のコマンドを使用します。

    gcloud run deploy \
    --image=IMAGE \
    --add-cloudsql-instances=CLOUD_SQL_CONNECTION_NAME
                
    既存のサービスを更新する場合は、次のコマンドを使用します。
    gcloud run services update SERVICE_NAME \
    --add-cloudsql-instances=CLOUD_SQL_CONNECTION_NAME
                

プライベート IP

サーバーレス VPC アクセス コネクタは VPC ネットワークとの通信を処理します。 プライベート IP に直接接続するには、次のようにする必要があります。

  1. 上述で作成した Cloud SQL インスタンスにプライベート IP アドレスが割り当てられていることを確認します。プライベート IP を追加する必要がある場合は、プライベート IP の構成ページの手順をご覧ください。
  2. Cloud SQL インスタンスと同じ VPC ネットワークにサーバーレス VPC アクセス コネクタを作成します。
  3. 共有 VPC を使用している場合を除き、コネクタは、それを使用するリソースと同じプロジェクトとリージョン内に配置されている必要がありますが、異なるリージョンのリソースにトラフィックを送信できます。

    サーバーレス VPC アクセスでは、Cloud VPNVPC ネットワーク ピアリングを介して接続された VPC ネットワークとの通信がサポートされています。

    サーバーレス VPC アクセスは、レガシー ネットワークをサポートしていません。

  4. コネクタを使用するように Cloud Run を構成します
  5. インスタンスのプライベート IP とポート 5432 を使用して接続します。

Cloud SQL への接続

Cloud Run を構成すると、Cloud SQL インスタンスに接続できます。

パブリック IP(デフォルト)

パブリック IP パスの場合は、Cloud Run によって暗号化が行われ、Cloud SQL Auth プロキシを使用して Unix ソケット経由で接続します。

Unix ソケットによる接続

正しく構成されたら、パス /cloudsql/INSTANCE_CONNECTION_NAME で環境のファイルシステムからアクセスされる Cloud SQL インスタンスの Unix ドメイン ソケットにサービスを接続できます。

INSTANCE_CONNECTION_NAME は、Google Cloud Console のインスタンスの [概要] ページで確認できます。また、次のコマンドで確認することもできます。

gcloud sql instances describe [INSTANCE_NAME]

これらの接続は、追加構成なしで自動的に暗号化されます。

以下に示すコードサンプルは、GitHub サイトに掲載されているより詳細な例からの抜粋です。詳しく見るには、View on GitHub をクリックしてください。

Python

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

# Remember - storing secrets in plaintext is potentially unsafe. Consider using
# something like https://cloud.google.com/secret-manager/docs/overview to help keep
# secrets secret.
db_user = os.environ["DB_USER"]
db_pass = os.environ["DB_PASS"]
db_name = os.environ["DB_NAME"]
db_socket_dir = os.environ.get("DB_SOCKET_DIR", "/cloudsql")
cloud_sql_connection_name = os.environ["CLOUD_SQL_CONNECTION_NAME"]

pool = sqlalchemy.create_engine(

    # Equivalent URL:
    # postgresql+pg8000://<db_user>:<db_pass>@/<db_name>
    #                         ?unix_sock=<socket_path>/<cloud_sql_instance_name>/.s.PGSQL.5432
    sqlalchemy.engine.url.URL.create(
        drivername="postgresql+pg8000",
        username=db_user,  # e.g. "my-database-user"
        password=db_pass,  # e.g. "my-database-password"
        database=db_name,  # e.g. "my-database-name"
        query={
            "unix_sock": "{}/{}/.s.PGSQL.5432".format(
                db_socket_dir,  # e.g. "/cloudsql"
                cloud_sql_connection_name)  # i.e "<PROJECT-NAME>:<INSTANCE-REGION>:<INSTANCE-NAME>"
        }
    ),
    **db_config
)

Java

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

// Note: For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections
// which is preferred to using the Cloud SQL Auth Proxy with Unix sockets.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.

// The configuration object specifies behaviors for the connection pool.
HikariConfig config = new HikariConfig();

// The following URL is equivalent to setting the config options below:
// jdbc:postgresql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=<DB_USER>&password=<DB_PASS>
// See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
// https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url

// Configure which instance and what database user to connect with.
config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "postgres"
config.setPassword(DB_PASS); // e.g. "my-password"

config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);

// The ipTypes argument can be used to specify a comma delimited list of preferred IP types
// for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
// SocketFactory to connect with an instance's associated private IP.
config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");

// ... Specify additional connection properties here.
// ...

// Initialize the connection pool using the configuration object.
DataSource pool = new HikariDataSource(config);

Node.js

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

const createUnixSocketPool = async config => {
  const dbSocketPath = process.env.DB_SOCKET_PATH || '/cloudsql';

  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: process.env.DB_USER, // e.g. 'my-user'
      password: process.env.DB_PASS, // e.g. 'my-user-password'
      database: process.env.DB_NAME, // e.g. 'my-database'
      host: `${dbSocketPath}/${process.env.CLOUD_SQL_CONNECTION_NAME}`,
    },
    // ... Specify additional properties here.
    ...config,
  });
};

C#

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

// Equivalent connection string:
// "Server=<dbSocketDir>/<INSTANCE_CONNECTION_NAME>;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>"
String dbSocketDir = Environment.GetEnvironmentVariable("DB_SOCKET_PATH") ?? "/cloudsql";
String instanceConnectionName = Environment.GetEnvironmentVariable("INSTANCE_CONNECTION_NAME");
var connectionString = new NpgsqlConnectionStringBuilder()
{
    // The Cloud SQL proxy provides encryption between the proxy and instance.
    SslMode = SslMode.Disable,
    // Remember - storing secrets in plain text is potentially unsafe. Consider using
    // something like https://cloud.google.com/secret-manager/docs/overview to help keep
    // secrets secret.
    Host = String.Format("{0}/{1}", dbSocketDir, instanceConnectionName),
    Username = Environment.GetEnvironmentVariable("DB_USER"), // e.g. 'my-db-user
    Password = Environment.GetEnvironmentVariable("DB_PASS"), // e.g. 'my-db-password'
    Database = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'
};
connectionString.Pooling = true;
// Specify additional properties here.
return connectionString;

Go

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

var (
	dbUser                 = mustGetenv("DB_USER")                  // e.g. 'my-db-user'
	dbPwd                  = mustGetenv("DB_PASS")                  // e.g. 'my-db-password'
	instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
	dbName                 = mustGetenv("DB_NAME")                  // e.g. 'my-database'
)

socketDir, isSet := os.LookupEnv("DB_SOCKET_DIR")
if !isSet {
	socketDir = "/cloudsql"
}

dbURI := fmt.Sprintf("user=%s password=%s database=%s host=%s/%s", dbUser, dbPwd, dbName, socketDir, instanceConnectionName)

// dbPool is the pool of database connections.
dbPool, err := sql.Open("pgx", dbURI)
if err != nil {
	return nil, fmt.Errorf("sql.Open: %v", err)
}

// ...

return dbPool, nil

Ruby

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

production:
  adapter: postgresql
  # Configure additional properties here.
  username: <%= ENV["DB_USER"] %>  # e.g. "my-database-user"
  password: <%= ENV["DB_PASS"] %> # e.g. "my-database-password"
  database: <%= ENV.fetch("DB_NAME") { "vote_production" } %>
  # If connecting via unix domain socket, specify the socket path as host
  host:  "<%= ENV.fetch("DB_SOCKET_DIR") { '/cloudsql' } %>/<%= ENV["INSTANCE_CONNECTION_NAME"] %>"

PHP

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

// $username = 'your_db_user';
// $password = 'yoursupersecretpassword';
// $dbName = 'your_db_name';
// $connectionName = getenv("CLOUD_SQL_CONNECTION_NAME");
// $socketDir = getenv('DB_SOCKET_DIR') ?: '/cloudsql';

// Connect using UNIX sockets
$dsn = sprintf(
    'pgsql:dbname=%s;host=%s/%s',
    $dbName,
    $socketDir,
    $connectionName
);

// Connect to the database.
$conn = new PDO($dsn, $username, $password, $connConfig);

SQL 認証情報などの機密情報の格納には、Secret Manager を使用することをおすすめします。Cloud Run を使用すると、シークレットを環境変数として渡すか、ボリュームとしてマウントできます。

Secret Manager でシークレットを作成した後、次のコマンドを使用して既存のサービスを更新します。

gcloud run services update SERVICE_NAME \
--add-cloudsql-instances=CLOUD_SQL_CONNECTION_NAME
--update-env-vars=CLOUD_SQL_CONNECTION_NAME=CLOUD_SQL_CONNECTION_NAME_SECRET \
--update-secrets=DB_USER=DB_USER_SECRET:latest \
--update-secrets=DB_PASS=DB_PASS_SECRET:latest \
--update-secrets=DB_NAME=DB_NAME_SECRET:latest
  

このコマンドの例では、シークレット バージョン latest を使用しています。ただし、シークレットを特定のバージョン SECRET_NAME:v1 に固定することをおすすめします。

プライベート IP

プライベート IP パスの場合、アプリケーションはサーバーレス VPC アクセスを介してインスタンスに直接接続します。この方法では、Cloud SQL Auth Proxy を使用せずに、TCP を使用して Cloud SQL インスタンスに直接接続します。

TCP による接続

インスタンスのプライベート IP アドレスとポート 5432 を使用して直接接続します。

Python

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

# Remember - storing secrets in plaintext is potentially unsafe. Consider using
# something like https://cloud.google.com/secret-manager/docs/overview to help keep
# secrets secret.
db_user = os.environ["DB_USER"]
db_pass = os.environ["DB_PASS"]
db_name = os.environ["DB_NAME"]
db_host = os.environ["DB_HOST"]

# Extract port from db_host if present,
# otherwise use DB_PORT environment variable.
host_args = db_host.split(":")
if len(host_args) == 1:
    db_hostname = db_host
    db_port = os.environ["DB_PORT"]
elif len(host_args) == 2:
    db_hostname, db_port = host_args[0], int(host_args[1])

pool = sqlalchemy.create_engine(
    # Equivalent URL:
    # postgresql+pg8000://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
    sqlalchemy.engine.url.URL.create(
        drivername="postgresql+pg8000",
        username=db_user,  # e.g. "my-database-user"
        password=db_pass,  # e.g. "my-database-password"
        host=db_hostname,  # e.g. "127.0.0.1"
        port=db_port,  # e.g. 5432
        database=db_name  # e.g. "my-database-name"
    ),
    **db_config
)

Java

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

注:

  • CLOUD_SQL_CONNECTION_NAME は <MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME> のように指定する必要があります。
  • 引数 ipTypes=PRIVATE を使用すると、SocketFactory はインスタンスに関連付けられたプライベート IP を使用して接続するようになります。
  • pom.xml ファイルの JDBC ソケット ファクトリ バージョン要件については、こちらをご覧ください。

// Note: For Java users, the Cloud SQL JDBC Socket Factory can provide authenticated connections
// which is preferred to using the Cloud SQL Auth Proxy with Unix sockets.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.

// The configuration object specifies behaviors for the connection pool.
HikariConfig config = new HikariConfig();

// The following URL is equivalent to setting the config options below:
// jdbc:postgresql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.postgres.SocketFactory&user=<DB_USER>&password=<DB_PASS>
// See the link below for more info on building a JDBC URL for the Cloud SQL JDBC Socket Factory
// https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory#creating-the-jdbc-url

// Configure which instance and what database user to connect with.
config.setJdbcUrl(String.format("jdbc:postgresql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "postgres"
config.setPassword(DB_PASS); // e.g. "my-password"

config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.postgres.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);

// The ipTypes argument can be used to specify a comma delimited list of preferred IP types
// for connecting to a Cloud SQL instance. The argument ipTypes=PRIVATE will force the
// SocketFactory to connect with an instance's associated private IP.
config.addDataSourceProperty("ipTypes", "PUBLIC,PRIVATE");

// ... Specify additional connection properties here.
// ...

// Initialize the connection pool using the configuration object.
DataSource pool = new HikariDataSource(config);

Node.js

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

const createTcpPool = async config => {
  // Extract host and port from socket address
  const dbSocketAddr = process.env.DB_HOST.split(':'); // e.g. '127.0.0.1:5432'

  // Establish a connection to the database
  return Knex({
    client: 'pg',
    connection: {
      user: process.env.DB_USER, // e.g. 'my-user'
      password: process.env.DB_PASS, // e.g. 'my-user-password'
      database: process.env.DB_NAME, // e.g. 'my-database'
      host: dbSocketAddr[0], // e.g. '127.0.0.1'
      port: dbSocketAddr[1], // e.g. '5432'
    },
    // ... Specify additional properties here.
    ...config,
  });
};

Go

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

var (
	dbUser    = mustGetenv("DB_USER") // e.g. 'my-db-user'
	dbPwd     = mustGetenv("DB_PASS") // e.g. 'my-db-password'
	dbTCPHost = mustGetenv("DB_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
	dbPort    = mustGetenv("DB_PORT") // e.g. '5432'
	dbName    = mustGetenv("DB_NAME") // e.g. 'my-database'
)

dbURI := fmt.Sprintf("host=%s user=%s password=%s port=%s database=%s", dbTCPHost, dbUser, dbPwd, dbPort, dbName)

// ...

// dbPool is the pool of database connections.
dbPool, err := sql.Open("pgx", dbURI)
if err != nil {
	return nil, fmt.Errorf("sql.Open: %v", err)
}

// ...

return dbPool, nil

C#

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

            // Equivalent connection string:
            // "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<DB_HOST>;Database=<DB_NAME>;"
            var connectionString = new NpgsqlConnectionStringBuilder()
            {
                // The Cloud SQL proxy provides encryption between the proxy and instance.
                SslMode = SslMode.Disable,

                // Remember - storing secrets in plain text is potentially unsafe. Consider using
                // something like https://cloud.google.com/secret-manager/docs/overview to help keep
                // secrets secret.
                Host = Environment.GetEnvironmentVariable("DB_HOST"),     // e.g. '127.0.0.1'
                // Set Host to 'cloudsql' when deploying to App Engine Flexible environment
                Username = Environment.GetEnvironmentVariable("DB_USER"), // e.g. 'my-db-user'
                Password = Environment.GetEnvironmentVariable("DB_PASS"), // e.g. 'my-db-password'
                Database = Environment.GetEnvironmentVariable("DB_NAME"), // e.g. 'my-database'
            };
            connectionString.Pooling = true;
            // Specify additional properties here.
            return connectionString;

Ruby

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

development:
  adapter: postgresql
  # Configure additional properties here.
  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("DB_HOST") { "127.0.0.1" }%> # '172.17.0.1' if deployed to GAE Flex
  port: <%= ENV.fetch("DB_PORT")  { 5432 }%>

PHP

このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。

// $username = 'your_db_user';
// $password = 'yoursupersecretpassword';
// $dbName = 'your_db_name';
// $dbHost = "127.0.0.1";

// Connect using TCP
$dsn = sprintf('pgsql:dbname=%s;host=%s', $dbName, $dbHost);

// Connect to the database
$conn = new PDO($dsn, $username, $password, $connConfig);

ベスト プラクティスとその他の情報

アプリケーションをローカルでテストする場合は、Cloud SQL Auth Proxy を使用できます。詳細な手順については、Cloud SQL Auth Proxy を使用するためのクイックスタートをご覧ください。

また、Docker コンテナ経由で Cloud SQL Proxy を使用してもテストできます。

接続プール

データベースサーバー自体またはプラットフォーム インフラストラクチャによって、基盤となるデータベースとの接続が切断される可能性があります。切断されたクライアント接続を自動的に再接続する接続プールをサポートするクライアント ライブラリを使用することをおすすめします。接続プールの使用方法の詳しい例については、データベース接続の管理ページをご覧ください。

接続上限

Cloud SQL の MySQL エディションと PostgreSQL エディションの両方で、同時接続の上限が設定されています。これらの上限は、選択したデータベース エンジンによって異なります(詳しくは、Cloud SQL の割り当てと上限ページをご覧ください)。

Cloud Run サービスは、Cloud SQL データベースに対する 100 接続に制限されています。この上限はサービス インスタンスごとに適用されます。つまり、Cloud Run サービスの各インスタンスはデータベースに対して 100 接続を保持できるため、スケールした場合にデプロイあたりの接続の合計数が増加する可能性があります。

インスタンスごとの最大接続数は、接続プールを使用して制限できます。接続数の制限方法の詳しい例については、データベース接続の管理ページをご覧ください。

API の割り当て上限

Cloud Run には、Cloud SQL API を使用する Cloud SQL Auth Proxy で接続する仕組みが用意されています。Cloud SQL Auth Proxy には API 割り当て上限が適用されます。使用される Cloud SQL Admin API の割り当ては、一度にデプロイされる特定のサービスの Cloud Run インスタンス数によって構成される Cloud SQL インスタンス数の約 2 倍です。想定される API 割り当ての使用量を変更するには、Cloud Run インスタンスの数を制限するか、増やしてください

次のステップ