Search code examples
google-app-enginegoogle-cloud-sqlsymfony-3.3google-app-engine-phpsymfony3

Symfony3 on Google App Engine Flexible can't connect to Google Cloud SQL MySQL


I can't get my Symfony 3 project on Google App Engine Flexible to connect to Google Cloud SQL (MySQL, 2. Generation).

Starting off with these examples

https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/appengine/flexible/symfony

https://github.com/GoogleCloudPlatform/php-docs-samples/tree/master/appengine/flexible/cloudsql-mysql

I created a Google App Engine and a Google Cloud SQL (MySQL, 2. Generation), both at europe-west3. I tested out these examples on my GAE and both run fine.

Then I went on and created a new, very simple Symfony 3.3 project from scratch. After creation (with only the welcome screen and "Your application is now ready. You can start working on it at: /app/") I deployed that to my GAEflex and it works fine.

After that I added one simple entity and an extra controller for that. This works fine, as it should, when starting Googles cloud_sql_proxy and the Symfony built-in webserver "php bin/console server:run". It reads and writes from and to the Cloud SQL, all easy peasy.

But, no matter what I tried I always get a "Connection Refused" on one (or the other, depending of my state of experimentation) of the commands from "symfony-scripts" "post-install-cmd" in my composer.json.

"$ gcloud beta app deploy" output (excerpt)

...
Step #1: Install PHP extensions...
Step #1: Running composer...
Step #1: Loading composer repositories with package information
...
Step #1:     [Doctrine\DBAL\Exception\ConnectionException]
Step #1:     An exception occurred in driver: SQLSTATE[HY000] [2002] Connection refused
Step #1:
Step #1:
Step #1:     [Doctrine\DBAL\Driver\PDOException]
Step #1:     SQLSTATE[HY000] [2002] Connection refused
Step #1:
Step #1:
Step #1:     [PDOException]
Step #1:     SQLSTATE[HY000] [2002] Connection refused
...

parameters.yml (excerpt)

parameters:
    database_host: 127.0.0.1
    database_port: 3306
    database_name: gae-test-project
    database_user: root
    database_password: secretpassword

config.yml (excerpt)

doctrine:
    dbal:
        driver: pdo_mysql
        host: '%database_host%'
        port: '%database_port%'
        unix_socket: '/cloudsql/restof:europe-west3:connectionname'
        dbname: '%database_name%'
        user: '%database_user%'
        password: '%database_password%'
        charset: utf8mb4
        default_table_options:
            charset: utf8mb4
            collate: utf8mb4_unicode_ci

composer.json (excerpt)

"require": {
    "php": "^7.1",
    "doctrine/doctrine-bundle": "^1.6",
    "doctrine/orm": "^2.5",
    "incenteev/composer-parameter-handler": "^2.0",
    "sensio/distribution-bundle": "^5.0.19",
    "sensio/framework-extra-bundle": "^3.0.2",
    "sensio/generator-bundle": "^3.0",
    "symfony/monolog-bundle": "^3.1.0",
    "symfony/polyfill-apcu": "^1.0",
    "symfony/swiftmailer-bundle": "^2.3.10",
    "symfony/symfony": "3.3.*",
    "twig/twig": "^1.0||^2.0"
},
"require-dev": {
    "symfony/phpunit-bridge": "^3.0"
},
"scripts": {
    "symfony-scripts": [
        "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
        "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
        "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
        "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
        "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
        "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
    ],
    "post-install-cmd": [
        "chmod -R ug+w $APP_DIR/var",
        "@symfony-scripts"
    ],
    "post-update-cmd": [
        "@symfony-scripts"
    ]
},

app.yml (complete)

service: default
runtime: php
env: flex

runtime_config:
  document_root: web

env_variables:
  SYMFONY_ENV: prod
  MYSQL_USER: root
  MYSQL_PASSWORD: secretpassword
  MYSQL_DSN: mysql:unix_socket=/cloudsql/restof:europe-west3:connectionname;dbname=gae-test-project
  WHITELIST_FUNCTIONS: libxml_disable_entity_loader

#[START cloudsql_settings]
# Use the connection name obtained when configuring your Cloud SQL instance.
beta_settings:
    cloud_sql_instances: "restof:europe-west3:connectionname"
#[END cloudsql_settings]

Keep in mind that I added or altered only lines which examples and documentation advised me to.

What Do I do wrong? The examples both work fine, a Symfony project connecting to the DB through a running cloud_sql_proxy works fine, when I try to get doctrine to connect to a CloudSQL from within an GAEflex I get no connection.

Can anyone spot the rookies mistake I might have made? Has anyone had this problem and maybe I forgot one or the other setting with the GAE or CloudSQL? Can anyone point me to a repository of a working Symfony3/Doctrine project that uses GAEFlex and CloudSQL?

I am stuck as I can't find any uptodate documentation about how to get this, rather obvious, combination to run. Any help is greatly appreciated!

Cheers /Carsten


Solution

  • I found it. I read this post Flexible env: post-deploy-cmd from composer.json it not being executed which yielded two interesting infos.

    1. App Engine Flex for PHP, doesn't run post-deploy-cmdany more
    2. just use post-install-cmd as a drop-in replacement, unless you need DB connection.

    So, during deployment, there is simply no database connection / socket available! That's why Google introduced the (non-standard) post-deploy-cmd which unfortunately seems to have caused some other trouble, so they removed it again. Bummer.

    In effect, as of to date, one can't use anything that utilizes the database within post-install-cmd.

    In the case above, I just changed

    composer.json (excerpt)

    "scripts": {
        "symfony-scripts": [
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
        ],
        "pre-install-cmd": [
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
        "post-install-cmd": [
            "chmod -R ug+w $APP_DIR/var",
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile",
            "Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::prepareDeploymentTarget"
        ],
        "post-update-cmd": [
            "@symfony-scripts"
        ]
    },
    

    And everything runs fine...

    I'm not sure about the innards of installAssets and if I still achieve the originally intended effect when I move it to pre-install but, well, it works for a very simple example application... In the next days I'm going to work on carrying this over to my more complex application and see if I can get that to work.

    Further discussion will most likely be over at the Google Cloud Platform Community

    Cheers everyone!