If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeWe just deployed a semi-working version of our site to platform.sh! All it took was one command to bootstrap a few config files and another to create the project inside of platform.sh.
But... we had some errors and warnings along the way. On top of the output, we see a warning about using an old composer version. In a minute, we'll see how and why composer is used during the deploy. But when it is, for some reason, it's currently using an old version of Composer.
Fortunately, it warns us and tells us how to fix it.
Copy this dependencies
line. Then, open .platform.app.yaml
. This is the main deploy file: almost every deploy tweak you'll make will be made here.
There are two steps to the deploy process. The first is the build
step where it's building your code: you can think of this as the step that prepares all the physical files that your project needs. Once the build
step is done, it spins up a container, puts the files inside and then runs the second and final part of the process: the deploy
step. This is where you can run some final commands.
See these symfony-build
and symfony-deploy
scripts? These are pre-made scripts that contain most of what your app needs to deploy. If you downloaded them and opened them up, you'd see things like running composer install
, warming up the cache and running database migrations. We can add custom stuff above or below.
The config has mounts
- for directories that you want to keep persistent between deploys - PHP extensions, your PHP version, and quite a bit more.
Anywhere inside, paste the dependencies
line... and make sure it's not indented.
... lines 1 - 4 | |
dependencies: | |
php: | |
composer/composer: "^2" | |
... lines 8 - 53 |
And just like that, we're using Composer version 2.
The second error that we had, down near the bottom, was,
could not find driver
This come from when the symfony-deploy
script tries to run our database migrations. Locally, we're using Postgres. You can see that in docker-compose.yml
. Do we have a database up on Platform.sh yet? The answer is... actually yes.
In addition to the main deploy file - .platform.app.yaml
- we have a /.platform
directory with a few other files. The most important is services.yaml
. This is where we define services like databases, Redis, Elasticsearch and others. When we initialized the project, it noticed that we're using Postgres and added a database for us!
... line 1 | |
database: | |
type: postgresql:15 | |
disk: 1024 |
The error we're getting isn't because it can't find the database: it's because our PHP install is missing the PDO_PGSQL
driver! And thanks to .platform.app.yaml
, adding that is easy.
Find extensions
, and add pdo_pgsql
.
... lines 1 - 8 | |
runtime: | |
extensions: | |
... lines 11 - 15 | |
- pdo_pgsql | |
... lines 17 - 53 |
Ok, ready to re-deploy? Remember: deploying happens via a push, so we need to commit these files. Run git commit -m
with an inspirational message.
git commit -m "tweaking deploy script"
Now run:
symfony deploy
This runs the same steps as our first deploy, which we now understand include a build
step then a deploy
step. It'll take a minute or two, but should be a bit faster because it doesn't need to re-provision the SSL certificate.
At the very end... the migration command still failed, but with a different error:
Connection refused
Ah, ignore that for a minute. Instead, go back to the site and refresh. The homepage still works. But... that's because our homepage doesn't use the database. If you hit "Browse Mixes"... 500 error! That 500 error is probably due to a database connection problem. But let's pretend that we have no idea what's causing this. How could we figure that out? This is where the
symfony logs
command comes in handy. This connects to whatever platform.sh "environment" - or "server" - that our current git branch is connected to and sends back log info. There are a bunch of choices - but hit 2
to go to the "app" log. This represents the Symfony logs coming from our app. And... oooh. I see several:
connection to server [..] failed: Connection refused
Let's think about this. We apparently do have Postgres set up, thanks to the services.yaml
file. But we never configured our app to talk to it. Remember, in .env
, we have a DATABASE_URL
env var that's supposed to point our database. We never configured that on our production site, so it's just using this default value. And no surprise, that's not working.
How can we configure DATABASE_URL
to point to... wherever this database server is? The answer is... we... uh... don't? And it's pretty cool.
Platform.sh has this idea of relationships. You have a number of services in services.yaml
. But your app can't talk to these until you link them together using what's called a "relationship".
Search .platform.app.yaml
for "relationships". It's not here yet, so let's add that. Each "relationship" has an internal name. It could technically be anything, but, in practice, you should use database
. We'll see the significance of that in a moment. Set this to the word database
, because that's the key we have here, then :
followed by the type of the service, which is postgresql
.
... lines 1 - 17 | |
relationships: | |
database: "database:postgresql" | |
... lines 20 - 56 |
This syntax has always looked weird to me. The important thing is that the key could be anything, like banana
, but this database
refers to this database
over in services.yaml
, and postgresql
refers to this postgresql
.
But though the first database
key could be anything, I used database
on purpose. Symfony does a really nice thing when it deploys via Platform.sh. It sees this relationship, notices it's for a database, and then automatically exposes an environment variable containing the connection info to that database!
What's this environment variable called? Since we used the key "database", it will be called DATABASE_URL
. In other words, it's going to set this environment variable for us. I'll prove it!
One of my favorite things about Platform.sh is that you can SSH onto your container. Watch:
symfony ssh
There we go. Once here, if you want to see every environment variable, run:
printenv
Look at that! You won't see anything that starts with "database", but we should after we deploy this next change. Type exit
, run
git status
and then
git add -p
That's what we want! Commit with
git commit -m "adding database relation"
And
symfony deploy
This time, it deploys way faster. Because we didn't change any application code, platform.sh was smart enough to use our old app code, instead of doing all that building again. We can see that:
Reusing existing build for this tree ID
And hey! This time, we see that it Successfully migrated
! Yea! it ran our migration with zero problems. When we spin over and check the site... it works. It's still missing all of our styling... but we'll fix that next. The important thing is that the database is working.
You can see the difference that made if you run
symfony ssh
and
printenv
This time, there are several DATABASE_
variables, including the most important DATABASE_URL
.
Ok, the final missing piece from our deployed site is... all of its assets! Let's see what's needed to deploy an AssetMapper site next.
"Houston: no signs of life"
Start the conversation!
// composer.json
{
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"babdev/pagerfanta-bundle": "^4.0", // v4.2.0
"doctrine/doctrine-bundle": "^2.7", // 2.10.0
"doctrine/doctrine-migrations-bundle": "^3.2", // 3.2.4
"doctrine/orm": "^2.12", // 2.15.2
"knplabs/knp-time-bundle": "^1.18", // v1.20.0
"pagerfanta/doctrine-orm-adapter": "^4.0", // v4.1.0
"pagerfanta/twig": "^4.0", // v4.1.0
"stof/doctrine-extensions-bundle": "^1.7", // v1.7.1
"symfony/asset": "6.3.*", // v6.3.0
"symfony/asset-mapper": "6.3.*", // v6.3.0
"symfony/console": "6.3.*", // v6.3.0
"symfony/dotenv": "6.3.*", // v6.3.0
"symfony/flex": "^2", // v2.3.1
"symfony/framework-bundle": "6.3.*", // v6.3.0
"symfony/http-client": "6.3.*", // v6.3.0
"symfony/monolog-bundle": "^3.0", // v3.8.0
"symfony/proxy-manager-bridge": "6.3.*", // v6.3.0
"symfony/runtime": "6.3.*", // v6.3.0
"symfony/stimulus-bundle": "^2.9", // v2.9.1
"symfony/twig-bundle": "6.3.*", // v6.3.0
"symfony/ux-turbo": "^2.9", // v2.9.1
"symfony/web-link": "6.3.*", // v6.3.0
"symfony/yaml": "6.3.*", // v6.3.0
"twig/extra-bundle": "^2.12|^3.0", // v3.6.1
"twig/twig": "^2.12|^3.0" // v3.6.1
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4", // 3.4.4
"symfony/debug-bundle": "6.3.*", // v6.3.0
"symfony/maker-bundle": "^1.41", // v1.49.0
"symfony/stopwatch": "6.3.*", // v6.3.0
"symfony/web-profiler-bundle": "6.3.*", // v6.3.0
"zenstruck/foundry": "^1.21" // v1.33.0
}
}