Scroll down to the script below, click on any sentence (including terminal blocks!) to jump to that spot in the video!
We just deployed to SymfonyCloud!!! Well, I mean, we did... but it doesn't... ya know... work yet. Because this is the production 500 error, we can't see the real problem.
No worries! Head back to your terminal. The
symfony command has an easy way to check the production logs. It is...
This prints a list of all the logs. The
app/ directory is where our application is deployed to - so the first item is our project's
var/log/prod.log file. You can also check out the raw access log... or everything. Hit 0 to "tail" the
prod.log file. And... there it is:
An exception has occurred... Connection refused.
I recognize this: it's a database error.... which... hmm... makes sense: we haven't told SymfonyCloud that we need a database! Let's go do that!
Google for "SymfonyCloud MySQL" to find... oh! A page that talks about exactly that. Ok, we need to add a little bit of config to 2 files. The first is
.symfony/services.yaml. This is where you tell SymfonyCloud about all the "services" you need - like a database service, ElasticSearch, Redis, RabbitMQ, etc.
Copy the config for
.symfony/services.yaml... then open that file and paste:
The database is actually MariaDB, which is why the version here is 10.2: MariaDB version 10.2.
Notice that we've used the key
mydatabase. That can be anything you want: we'll reference this string from the other config file that we need to change:
Inside that file, we need a
relationships key: this is what binds the web container to that database service. Let's see... we don't have a
relationships key yet, so let's add it:
relationships and, below, add our first relationship with a special string:
database set to
|... lines 1 - 24|
|... lines 27 - 42|
This syntax... is a little funny. The
mydatabase part is referring to whatever key we used in
services.yaml - and then we say
:mysql... because that service is a
The really important thing is that we called this relationship
database. Thanks to that
SymfonyCloud will expose an environment variable called
DATABASE_URL which contains the full MySQL connection string: username, host, database name and all:
|... lines 1 - 26|
|... lines 28 - 29|
DATABASE_URL and not
PIZZA_URL because we called the relationship
database instead of
pizza... which would have been less descriptive, but more delicious.
This is important because
DATABASE_URL happens to be the environment variable that our app will use to connect to the database. In other words, our app will instantly have database config.
Back at the terminal, hit
C to exit from logging. Let's add the two changes and commit them:
git add .git commit -m "adding SfCloud database"
Oh, duh - run with the
symfony deploy --bypass-checks
The deploy will still take some time - it has a lot of work to do - but it'll be faster than before. When it finishes... it dumps the same URL - that won't change. But to be even lazier than last time, let's tell the command to open this URL in my browser... for me:
And... we have a deployed site! Woo! The database is empty... but if this were a real app, it would start to be populated by real users entering their real Bigfoot sightings... cause Bigfoot is... totally real.
But... to make this a bit more interesting for us, let's load the fixture data one time on production.
This is a bit tricky because the fixture system - which comes from DoctrineFixturesBundle - is a Composer "dev" dependency... which means that it's not even installed on production. That's good for performance. If it were installed, we could run:
To SSH into our container, and then execute the command to load the fixtures. But... that won't work.
No problem! We can do something cooler. Exit out of SSH, and run:
I love this feature. Normally, the remote database isn't accessible by anything other than our container: you can't connect to it from anywhere else on the Internet. It's totally firewalled. But suddenly, we can connect to the production database locally on port 30000. We can use that to run the fixtures command locally - but send the data up to that database. Do it by running:
DATABASE_URL=mysql://root:@127.0.0.1:30000/main php bin/console doctrine:fixtures:load
Ok, let's break this down. First, there is actually a much easier way to do all of this... but I'll save that for some future SymfonyCloud tutorial. Basically, we're running the
doctrine:fixtures:load command but sending it a different
DATABASE_URL: one that points at our production database. When you open a tunnel, you can access the database with
root user, no password - and the database is called
The only problem is that this command... takes forever to run. I'm not sure exactly why - but it is doing all of this over a network. Go grab some coffee and come back in a few minutes.
When it finishes... yes! Go refresh the page! Ha! We have a production site with at least enough data to make profiling interesting.
Next, let's do that! Let's configure Blackfire on production! That's easy right? Just repeat the Blackfire install process on a different server... right? Yep! Wait, no! Yes! Bah! To explain, we need to talk about a wonderful concept in Blackfire called "environments".