このページには、App Engine フレキシブル環境で走行中のサービスから Cloud SQL インスタンスに接続するための情報と例が記載されています。
Cloud SQL は、クラウド内のリレーショナル データベースの設定、維持、管理に役立つフルマネージド データベース サービスです。
App Engine は、大規模なウェブ アプリケーションを開発およびホスティングするための、フルマネージド型のサーバーレス プラットフォームです。アプリの開発では複数の一般的な言語、ライブラリ、フレームワークからの選択が可能で、開発したアプリのインスタンスのサーバー プロビジョニングとスケーリングは App Engine によってオンデマンドで行われます。
Cloud SQL インスタンスを設定する
- 接続元の Google Cloud プロジェクトで Cloud SQL Admin API を有効にします(まだ有効にしていない場合)。
- Cloud SQL for MySQL インスタンスを作成します。Cloud SQL のインスタンス ロケーションは、Cloud Run サービスと同じリージョンを選択することをおすすめします。このようにすると、レイテンシを短縮して、ネットワーク費用を回避し、リージョン間の障害リスクを軽減することができます。
Cloud SQL は、デフォルトで新しいインスタンスにパブリック IP アドレスを割り振ります。 プライベート IP アドレスを割り当てることもできます。両方の接続オプションの詳細については、接続の概要ページをご覧ください。
App Engine フレキシブル環境を構成する
App Engine フレキシブル環境を構成する手順は、Cloud SQL インスタンスに割り当てられた IP アドレスのタイプによって異なります。パブリック IP(デフォルト)
Cloud SQL インスタンスへの接続を有効にするように App Engine フレキシブル環境を構成するには:
- インスタンスにパブリック IP アドレスがあることを確認します。これは、Google Cloud コンソールのインスタンスの [概要] ページで確認できます。パブリック IP を追加する必要がある場合は、パブリック IP の構成ページの手順をご覧ください。
- インスタンスの INSTANCE_CONNECTION_NAME を取得します。この値は、Google Cloud コンソールのインスタンスの [概要] ページに表示されます。また、次の
gcloud sql instances describe
コマンドで確認することもできます。 INSTANCE_NAME は、Cloud SQL インスタンスの名前に置き換えます。gcloud sql instances describe INSTANCE_NAME
- アプリが Cloud SQL の呼び出しを認証するために使用しているサービス アカウントに、適切な Cloud SQL のロールと権限があることを確認します。
- お使いのサービスのサービス アカウントには、次のいずれかの IAM ロールが必要です。
Cloud SQL Client
(推奨)Cloud SQL Editor
Cloud SQL Admin
cloudsql.instances.connect
cloudsql.instances.get
デフォルトでは、アプリは App Engine フレキシブル環境サービス アカウントを使用して接続を承認します。サービス アカウントの形式は
PROJECT_ID@appspot.gserviceaccount.com
です。サービス アカウントの承認が Cloud SQL インスタンスとは異なるプロジェクトに属している場合、Cloud SQL Admin API と IAM の権限を両方のプロジェクトに追加する必要があります。
- お使いのサービスのサービス アカウントには、次のいずれかの IAM ロールが必要です。
- 最適に機能するオプションを使用して、プロジェクトの
app.yaml
ファイルを更新します。インスタンスのカンマ区切りのリストを使用すると、複数のオプションを一度に指定できます。UNIX ドメイン ソケットの有効化
UNIX ドメイン ソケットを有効にするには、1 つのインスタンスに接続するのか、複数のインスタンスに接続するのかに応じて、次のいずれかをプロジェクトの
app.yaml
ファイルに追加します。beta_settings: cloud_sql_instances: INSTANCE_CONNECTION_NAME
beta_settings: cloud_sql_instances: INSTANCE_CONNECTION_NAME,INSTANCE_CONNECTION_NAME_2,...
TCP ポートの有効化
ローカル TCP ポートを有効にするには、1 つのインスタンスに接続するのか、複数のインスタンスに接続するのかに応じて、次のいずれかをプロジェクトのapp.yaml
ファイルに追加します。beta_settings: cloud_sql_instances: INSTANCE_CONNECTION_NAME=tcp:PORT
beta_settings: cloud_sql_instances: INSTANCE_CONNECTION_NAME_1=tcp:PORT_1,INSTANCE_CONNECTION_NAME_2=tcp:PORT_2,...
プライベート IP
プライベート IP 経由で Cloud SQL インスタンスに接続するには、App Engine フレキシブル環境のデプロイメントが Cloud SQL インスタンスと同じ VPC ネットワークに存在する必要があります。デプロイで VPC ネットワークを指定する方法については、ネットワーク設定の構成に関するドキュメントをご覧ください。
デプロイ後、アプリケーションはインスタンスのプライベート IP アドレスとポート 3306
を使用して直接接続できるようになります。
Cloud SQL への接続
App Engine フレキシブル環境を構成すると、Cloud SQL インスタンスに接続できます。
パブリック IP(デフォルト)
パブリック IP パスの場合、App Engine フレキシブル環境では、次の 3 つの方法で Cloud SQL Auth Proxy を使用して暗号化と接続が行われます。
- TCP ソケット経由
- Unix ソケット経由
- Cloud SQL コネクタを使用
TCP による接続
172.17.0.1:PORT
を使用して直接接続します。ここで PORT
は app.yaml
ファイルで指定したポートです。Cloud SQL Auth Proxy は 172.17.0.1
でリッスンし、接続を暗号化して Cloud SQL インスタンスに転送します。
Python
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
import os
import sqlalchemy
def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
"""Initializes a TCP connection pool for a Cloud SQL instance of MySQL."""
# 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. 3306
pool = sqlalchemy.create_engine(
# Equivalent URL:
# mysql+pymysql://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
sqlalchemy.engine.url.URL.create(
drivername="mysql+pymysql",
username=db_user,
password=db_pass,
host=db_host,
port=db_port,
database=db_name,
),
# ...
)
return pool
Java
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
注:
- INSTANCE_CONNECTION_NAME は、<MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME> として表す必要があります。
- 引数 ipTypes=PRIVATE を使用すると、SocketFactory はインスタンスに関連付けられたプライベート IP を使用して接続するようになります。
- pom.xml ファイルの JDBC ソケット ファクトリ バージョン要件については、こちらをご覧ください。
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
public class TcpConnectionPoolFactory extends ConnectionPoolFactory {
// Saving credentials in environment variables is convenient, but not secure - consider a more
// secure solution such as https://cloud.google.com/secret-manager/ to help keep secrets safe.
private static final String DB_USER = System.getenv("DB_USER");
private static final String DB_PASS = System.getenv("DB_PASS");
private static final String DB_NAME = System.getenv("DB_NAME");
private static final String INSTANCE_HOST = System.getenv("INSTANCE_HOST");
private static final String DB_PORT = System.getenv("DB_PORT");
public static DataSource createConnectionPool() {
// 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:mysql://<INSTANCE_HOST>:<DB_PORT>/<DB_NAME>?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:mysql://%s:%s/%s", INSTANCE_HOST, DB_PORT, DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "mysql"
config.setPassword(DB_PASS); // e.g. "my-password"
// ... Specify additional connection properties here.
// ...
// Initialize the connection pool using the configuration object.
return new HikariDataSource(config);
}
}
Node.js
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
const mysql = require('promise-mysql');
const fs = require('fs');
// createTcpPool initializes a TCP connection pool for a Cloud SQL
// instance of MySQL.
const createTcpPool = async config => {
// 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.
const dbConfig = {
host: process.env.INSTANCE_HOST, // e.g. '127.0.0.1'
port: process.env.DB_PORT, // e.g. '3306'
user: 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'
// ... Specify additional properties here.
...config,
};
// Establish a connection to the database.
return mysql.createPool(dbConfig);
};
Go
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
package cloudsql
import (
"crypto/tls"
"crypto/x509"
"database/sql"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/go-sql-driver/mysql"
)
// connectTCPSocket initializes a TCP connection pool for a Cloud SQL
// instance of MySQL.
func connectTCPSocket() (*sql.DB, error) {
mustGetenv := func(k string) string {
v := os.Getenv(k)
if v == "" {
log.Fatalf("Fatal Error in connect_tcp.go: %s environment variable not set.", k)
}
return v
}
// 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'
dbName = mustGetenv("DB_NAME") // e.g. 'my-database'
dbPort = mustGetenv("DB_PORT") // e.g. '3306'
dbTCPHost = mustGetenv("INSTANCE_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
)
dbURI := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true",
dbUser, dbPwd, dbTCPHost, dbPort, dbName)
// dbPool is the pool of database connections.
dbPool, err := sql.Open("mysql", dbURI)
if err != nil {
return nil, fmt.Errorf("sql.Open: %w", err)
}
// ...
return dbPool, nil
}
C#
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
using MySql.Data.MySqlClient;
using System;
namespace CloudSql
{
public class MySqlTcp
{
public static MySqlConnectionStringBuilder NewMysqlTCPConnectionString()
{
// Equivalent connection string:
// "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<INSTANCE_HOST>;Database=<DB_NAME>;"
var connectionString = new MySqlConnectionStringBuilder()
{
// 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.
Server = Environment.GetEnvironmentVariable("INSTANCE_HOST"), // e.g. '127.0.0.1'
// Set Host to 'cloudsql' when deploying to App Engine Flexible environment
UserID = 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'
// The Cloud SQL proxy provides encryption between the proxy and instance.
SslMode = MySqlSslMode.Disabled,
};
connectionString.Pooling = true;
// Specify additional properties here.
return connectionString;
}
}
}
Ruby
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
tcp: &tcp
adapter: mysql2
# 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 Flex
port: <%= ENV.fetch("DB_PORT") { 3306 }%>
PHP
ウェブ アプリケーションのコンテキストでのこのスニペットの使用については、GitHub の README をご覧ください。
namespace Google\Cloud\Samples\CloudSQL\MySQL;
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('mysql:dbname=%s;host=%s', $dbName, $instanceHost);
// 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/mysql/connect-external-app',
$e->getMessage()
),
$e->getCode(),
$e
);
}
return $conn;
}
}
Unix ソケットによる接続
正しく構成されたら、パス /cloudsql/INSTANCE_CONNECTION_NAME
で環境のファイルシステムからアクセスされる Cloud SQL インスタンスの Unix ドメイン ソケットにサービスを接続できます。
INSTANCE_CONNECTION_NAME は project:region:instance-id
形式を使用します。これは、Google Cloud コンソールのインスタンスの [概要] ページに表示されます。また、次のコマンドで確認することもできます。
gcloud sql instances describe [INSTANCE_NAME]
これらの接続は、追加構成なしで自動的に暗号化されます。
以下に示すコードサンプルは、GitHub サイトに掲載されている詳細な例からの抜粋です。詳しく見るには、View on GitHub
をクリックしてください。
Python
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
import os
import sqlalchemy
def connect_unix_socket() -> sqlalchemy.engine.base.Engine:
"""Initializes a Unix socket connection pool for a Cloud SQL instance of MySQL."""
# 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_user = os.environ["DB_USER"] # e.g. 'my-database-user'
db_pass = os.environ["DB_PASS"] # e.g. 'my-database-password'
db_name = os.environ["DB_NAME"] # e.g. 'my-database'
unix_socket_path = os.environ[
"INSTANCE_UNIX_SOCKET"
] # e.g. '/cloudsql/project:region:instance'
pool = sqlalchemy.create_engine(
# Equivalent URL:
# mysql+pymysql://<db_user>:<db_pass>@/<db_name>?unix_socket=<socket_path>/<cloud_sql_instance_name>
sqlalchemy.engine.url.URL.create(
drivername="mysql+pymysql",
username=db_user,
password=db_pass,
database=db_name,
query={"unix_socket": unix_socket_path},
),
# ...
)
return pool
Java
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
public class ConnectorConnectionPoolFactory extends ConnectionPoolFactory {
// 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.
private static final String INSTANCE_CONNECTION_NAME =
System.getenv("INSTANCE_CONNECTION_NAME");
private static final String INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
private static final String DB_USER = System.getenv("DB_USER");
private static final String DB_PASS = System.getenv("DB_PASS");
private static final String DB_NAME = System.getenv("DB_NAME");
public static DataSource createConnectionPool() {
// 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:mysql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.mysql.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:mysql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "mysql"
config.setPassword(DB_PASS); // e.g. "my-password"
config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.SocketFactory");
config.addDataSourceProperty("cloudSqlInstance", INSTANCE_CONNECTION_NAME);
// Unix sockets are not natively supported in Java, so it is necessary to use the Cloud SQL
// Java Connector to connect. When setting INSTANCE_UNIX_SOCKET, the connector will
// call an external package that will enable Unix socket connections.
// Note: For Java users, the Cloud SQL Java Connector can provide authenticated connections
// which is usually preferable to using the Cloud SQL Proxy with Unix sockets.
// See https://github.com/GoogleCloudPlatform/cloud-sql-jdbc-socket-factory for details.
if (INSTANCE_UNIX_SOCKET != null) {
config.addDataSourceProperty("unixSocketPath", INSTANCE_UNIX_SOCKET);
}
// ... Specify additional connection properties here.
// ...
// Initialize the connection pool using the configuration object.
return new HikariDataSource(config);
}
}
Node.js
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
const mysql = require('promise-mysql');
// createUnixSocketPool initializes a Unix socket connection pool for
// a Cloud SQL instance of MySQL.
const createUnixSocketPool = async config => {
// 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.
return mysql.createPool({
user: 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'
socketPath: process.env.INSTANCE_UNIX_SOCKET, // e.g. '/cloudsql/project:region:instance'
// Specify additional properties here.
...config,
});
};
C#
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
using MySql.Data.MySqlClient;
using System;
namespace CloudSql
{
public class MySqlUnix
{
public static MySqlConnectionStringBuilder NewMysqlUnixSocketConnectionString()
{
// Equivalent connection string:
// "Server=<INSTANCE_UNIX_SOCKET>;Uid=<DB_USER>;Pwd=<DB_PASS>;Database=<DB_NAME>;Protocol=unix"
var connectionString = new MySqlConnectionStringBuilder()
{
// The Cloud SQL proxy provides encryption between the proxy and instance.
SslMode = MySqlSslMode.Disabled,
// 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.
Server = Environment.GetEnvironmentVariable("INSTANCE_UNIX_SOCKET"), // e.g. '/cloudsql/project:region:instance'
UserID = 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'
ConnectionProtocol = MySqlConnectionProtocol.UnixSocket
};
connectionString.Pooling = true;
// Specify additional properties here.
return connectionString;
}
}
}
Go
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
package cloudsql
import (
"database/sql"
"fmt"
"log"
"os"
_ "github.com/go-sql-driver/mysql"
)
// connectUnixSocket initializes a Unix socket connection pool for
// a Cloud SQL instance of MySQL.
func connectUnixSocket() (*sql.DB, error) {
mustGetenv := func(k string) string {
v := os.Getenv(k)
if v == "" {
log.Fatalf("Fatal Error in connect_unix.go: %s environment variable not set.", k)
}
return v
}
// 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'
dbName = mustGetenv("DB_NAME") // e.g. 'my-database'
unixSocketPath = mustGetenv("INSTANCE_UNIX_SOCKET") // e.g. '/cloudsql/project:region:instance'
)
dbURI := fmt.Sprintf("%s:%s@unix(%s)/%s?parseTime=true",
dbUser, dbPwd, unixSocketPath, dbName)
// dbPool is the pool of database connections.
dbPool, err := sql.Open("mysql", dbURI)
if err != nil {
return nil, fmt.Errorf("sql.Open: %w", err)
}
// ...
return dbPool, nil
}
Ruby
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
unix: &unix
adapter: mysql2
# 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" } %>
# Specify the Unix socket path as host
socket: "<%= ENV["INSTANCE_UNIX_SOCKET"] %>"
PHP
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
namespace Google\Cloud\Samples\CloudSQL\MySQL;
use PDO;
use PDOException;
use RuntimeException;
use TypeError;
class DatabaseUnix
{
public static function initUnixDatabaseConnection(): 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'
$instanceUnixSocket = getenv('INSTANCE_UNIX_SOCKET'); // e.g. '/cloudsql/project:region:instance'
// Connect using UNIX sockets
$dsn = sprintf(
'mysql:dbname=%s;unix_socket=%s',
$dbName,
$instanceUnixSocket
);
// 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 $instanceUnixSocket (for UNIX socket mode). ' .
'The PHP error was %s',
$e->getMessage()
),
(int) $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/mysql/connect-external-app',
$e->getMessage()
),
(int) $e->getCode(),
$e
);
}
return $conn;
}
}
Cloud SQL コネクタによる接続
Cloud SQL コネクタは、Cloud SQL インスタンスへの接続時に暗号化と IAM ベースの承認を行う言語固有のライブラリです。
Python
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
import os
from google.cloud.sql.connector import Connector, IPTypes
import pymysql
import sqlalchemy
def connect_with_connector() -> sqlalchemy.engine.base.Engine:
"""
Initializes a connection pool for a Cloud SQL instance of MySQL.
Uses the Cloud SQL Python Connector package.
"""
# 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.
instance_connection_name = os.environ[
"INSTANCE_CONNECTION_NAME"
] # e.g. 'project:region:instance'
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'
ip_type = IPTypes.PRIVATE if os.environ.get("PRIVATE_IP") else IPTypes.PUBLIC
connector = Connector(ip_type)
def getconn() -> pymysql.connections.Connection:
conn: pymysql.connections.Connection = connector.connect(
instance_connection_name,
"pymysql",
user=db_user,
password=db_pass,
db=db_name,
)
return conn
pool = sqlalchemy.create_engine(
"mysql+pymysql://",
creator=getconn,
# ...
)
return pool
Java
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
注:
- INSTANCE_CONNECTION_NAME は、<MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME> として表す必要があります。
- pom.xml ファイルの JDBC ソケット ファクトリ バージョン要件については、こちらをご覧ください。
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
public class ConnectorConnectionPoolFactory extends ConnectionPoolFactory {
// 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.
private static final String INSTANCE_CONNECTION_NAME =
System.getenv("INSTANCE_CONNECTION_NAME");
private static final String INSTANCE_UNIX_SOCKET = System.getenv("INSTANCE_UNIX_SOCKET");
private static final String DB_USER = System.getenv("DB_USER");
private static final String DB_PASS = System.getenv("DB_PASS");
private static final String DB_NAME = System.getenv("DB_NAME");
public static DataSource createConnectionPool() {
// 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:mysql:///<DB_NAME>?cloudSqlInstance=<INSTANCE_CONNECTION_NAME>&
// socketFactory=com.google.cloud.sql.mysql.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:mysql:///%s", DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "mysql"
config.setPassword(DB_PASS); // e.g. "my-password"
config.addDataSourceProperty("socketFactory", "com.google.cloud.sql.mysql.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.
return new HikariDataSource(config);
}
}
Go
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
package cloudsql
import (
"context"
"database/sql"
"fmt"
"log"
"net"
"os"
"cloud.google.com/go/cloudsqlconn"
"github.com/go-sql-driver/mysql"
)
func connectWithConnector() (*sql.DB, error) {
mustGetenv := func(k string) string {
v := os.Getenv(k)
if v == "" {
log.Fatalf("Fatal Error in connect_connector.go: %s environment variable not set.", k)
}
return v
}
// 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 passwords and other secrets safe.
var (
dbUser = mustGetenv("DB_USER") // e.g. 'my-db-user'
dbPwd = mustGetenv("DB_PASS") // e.g. 'my-db-password'
dbName = mustGetenv("DB_NAME") // e.g. 'my-database'
instanceConnectionName = mustGetenv("INSTANCE_CONNECTION_NAME") // e.g. 'project:region:instance'
usePrivate = os.Getenv("PRIVATE_IP")
)
d, err := cloudsqlconn.NewDialer(context.Background())
if err != nil {
return nil, fmt.Errorf("cloudsqlconn.NewDialer: %w", err)
}
var opts []cloudsqlconn.DialOption
if usePrivate != "" {
opts = append(opts, cloudsqlconn.WithPrivateIP())
}
mysql.RegisterDialContext("cloudsqlconn",
func(ctx context.Context, addr string) (net.Conn, error) {
return d.Dial(ctx, instanceConnectionName, opts...)
})
dbURI := fmt.Sprintf("%s:%s@cloudsqlconn(localhost:3306)/%s?parseTime=true",
dbUser, dbPwd, dbName)
dbPool, err := sql.Open("mysql", dbURI)
if err != nil {
return nil, fmt.Errorf("sql.Open: %w", err)
}
return dbPool, nil
}
プライベート IP
TCP による接続
Cloud SQL インスタンスのプライベート IP アドレスをホストとポートの 3306
として使用して接続します。
Python
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
import os
import sqlalchemy
def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
"""Initializes a TCP connection pool for a Cloud SQL instance of MySQL."""
# 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. 3306
pool = sqlalchemy.create_engine(
# Equivalent URL:
# mysql+pymysql://<db_user>:<db_pass>@<db_host>:<db_port>/<db_name>
sqlalchemy.engine.url.URL.create(
drivername="mysql+pymysql",
username=db_user,
password=db_pass,
host=db_host,
port=db_port,
database=db_name,
),
# ...
)
return pool
Java
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
注:
- INSTANCE_CONNECTION_NAME は、<MY-PROJECT>:<INSTANCE-REGION>:<INSTANCE-NAME> として表す必要があります。
- 引数 ipTypes=PRIVATE を使用すると、SocketFactory はインスタンスに関連付けられたプライベート IP を使用して接続するようになります。
- pom.xml ファイルの JDBC ソケット ファクトリ バージョン要件については、こちらをご覧ください。
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
public class TcpConnectionPoolFactory extends ConnectionPoolFactory {
// Saving credentials in environment variables is convenient, but not secure - consider a more
// secure solution such as https://cloud.google.com/secret-manager/ to help keep secrets safe.
private static final String DB_USER = System.getenv("DB_USER");
private static final String DB_PASS = System.getenv("DB_PASS");
private static final String DB_NAME = System.getenv("DB_NAME");
private static final String INSTANCE_HOST = System.getenv("INSTANCE_HOST");
private static final String DB_PORT = System.getenv("DB_PORT");
public static DataSource createConnectionPool() {
// 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:mysql://<INSTANCE_HOST>:<DB_PORT>/<DB_NAME>?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:mysql://%s:%s/%s", INSTANCE_HOST, DB_PORT, DB_NAME));
config.setUsername(DB_USER); // e.g. "root", "mysql"
config.setPassword(DB_PASS); // e.g. "my-password"
// ... Specify additional connection properties here.
// ...
// Initialize the connection pool using the configuration object.
return new HikariDataSource(config);
}
}
Node.js
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
const mysql = require('promise-mysql');
const fs = require('fs');
// createTcpPool initializes a TCP connection pool for a Cloud SQL
// instance of MySQL.
const createTcpPool = async config => {
// 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.
const dbConfig = {
host: process.env.INSTANCE_HOST, // e.g. '127.0.0.1'
port: process.env.DB_PORT, // e.g. '3306'
user: 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'
// ... Specify additional properties here.
...config,
};
// Establish a connection to the database.
return mysql.createPool(dbConfig);
};
Go
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
package cloudsql
import (
"crypto/tls"
"crypto/x509"
"database/sql"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/go-sql-driver/mysql"
)
// connectTCPSocket initializes a TCP connection pool for a Cloud SQL
// instance of MySQL.
func connectTCPSocket() (*sql.DB, error) {
mustGetenv := func(k string) string {
v := os.Getenv(k)
if v == "" {
log.Fatalf("Fatal Error in connect_tcp.go: %s environment variable not set.", k)
}
return v
}
// 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'
dbName = mustGetenv("DB_NAME") // e.g. 'my-database'
dbPort = mustGetenv("DB_PORT") // e.g. '3306'
dbTCPHost = mustGetenv("INSTANCE_HOST") // e.g. '127.0.0.1' ('172.17.0.1' if deployed to GAE Flex)
)
dbURI := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true",
dbUser, dbPwd, dbTCPHost, dbPort, dbName)
// dbPool is the pool of database connections.
dbPool, err := sql.Open("mysql", dbURI)
if err != nil {
return nil, fmt.Errorf("sql.Open: %w", err)
}
// ...
return dbPool, nil
}
C#
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
using MySql.Data.MySqlClient;
using System;
namespace CloudSql
{
public class MySqlTcp
{
public static MySqlConnectionStringBuilder NewMysqlTCPConnectionString()
{
// Equivalent connection string:
// "Uid=<DB_USER>;Pwd=<DB_PASS>;Host=<INSTANCE_HOST>;Database=<DB_NAME>;"
var connectionString = new MySqlConnectionStringBuilder()
{
// 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.
Server = Environment.GetEnvironmentVariable("INSTANCE_HOST"), // e.g. '127.0.0.1'
// Set Host to 'cloudsql' when deploying to App Engine Flexible environment
UserID = 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'
// The Cloud SQL proxy provides encryption between the proxy and instance.
SslMode = MySqlSslMode.Disabled,
};
connectionString.Pooling = true;
// Specify additional properties here.
return connectionString;
}
}
}
Ruby
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
tcp: &tcp
adapter: mysql2
# 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 Flex
port: <%= ENV.fetch("DB_PORT") { 3306 }%>
PHP
このスニペットをウェブ アプリケーションのコンテキストで表示するには、GitHub の README をご覧ください。
namespace Google\Cloud\Samples\CloudSQL\MySQL;
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('mysql:dbname=%s;host=%s', $dbName, $instanceHost);
// 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/mysql/connect-external-app',
$e->getMessage()
),
$e->getCode(),
$e
);
}
return $conn;
}
}
ベスト プラクティスとその他の情報
アプリケーションをローカルでテストする場合は、Cloud SQL Auth Proxy を使用できます。詳細な手順については、Cloud SQL Auth Proxy を使用するためのクイックスタートをご覧ください。
接続プール
データベース サーバー自体、または基盤となるインフラストラクチャによって、基盤となるデータベースへの接続が切断される可能性があります。これを軽減するには、接続プールと自動再接続をサポートするクライアント ライブラリを使用することをおすすめします。
接続上限
スタンダード環境で実行される App Engine の各インスタンスでは、インスタンスに対する同時接続数が最大 100 個に制限されます。PHP 5.5 アプリケーションについては、同時接続数が最大 60 個に制限されます。この上限はアプリケーション インスタンスごとに適用されます。つまり、App Engine アプリケーションの各インスタンスはデータベースに対してこれだけ多くの接続を保持できるため、スケールするにつれて、デプロイあたりの接続の合計数が増加する可能性があります。詳しくは、要素のスケーリングをご覧ください。
インスタンスごとの最大接続数は、接続プールを使用して制限できます。接続数の制限方法の詳しい例については、データベース接続の管理ページをご覧ください。
App Engine アプリケーションでは、使用状況や環境に応じてリクエストに時間制限が設けられる場合があります。詳しくは、App Engine のスタンダード環境とフレキシブル環境におけるインスタンスの管理方法をご覧ください。
API の割り当て上限
App Engine には、Cloud SQL Admin API を使用する Cloud SQL Auth Proxy を使用して接続する仕組みが用意されています。Cloud SQL Auth Proxy には API 割り当て上限が適用されます。Cloud SQL Admin API の開始時に 2 つの割り当てが使用され、その後は 1 時間あたり平均 2 つが使用されます。デフォルトの割り当ては、1 ユーザー、1 分あたり 180 件です。さらに App Engine アプリケーションには、App Engine の割り当てページで説明されている App Engine の割り当てと上限も適用されます。