♪♪
-Hi, everyone. Welcome.
Hope you're doing well and are enjoying Deploy so far.
My name is Kamal Nasser.
I'm a software engineer on the app platform team
at DigitalOcean.
You can find me on Twitter and GitHub.
That's my username right there, and the goal of this talk today
is to give you a quick intro to App Platform
and to show you how to build and deploy your first web app on it
and also scale along with it as it grows.
Now, there are many different types of web apps out there
and to list just a few of them and to very broadly generalize,
we've got static sites,
files that are completely static.
There's no processing logic while the app is running.
We've got monoliths.
We've got microservice-based apps.
We've got traditional server-based ones
that render everything on the server itself.
They don't do any client-side rendering.
You've got JAMStack apps.
So if you've seen my colleague Jake's talk,
you'd see him deploy an R-assist reader app.
That is a react-based client-side front end
and an API written in Django running on the back end,
and there are also a bunch of different programming languages
that you can write or build your applications.
Now, all of these types of apps can run on App Platform.
The cool thing is, the process of deploying
a static site on App Platform
is just as simple as deploying a microservices-based app
or a JAMStack app with an API or a static site front end.
And that's because App Platform
does so much for you behind the scenes.
So everything from integrating with your development workflow,
the build process, which is compiling
and building your apps,
to deploying them and running them live on the web.
So no matter what programming language
you're using for your app,
App Platform is able to take that
and build it into a runnable application for you.
You don't have to worry about configuring HTTPS,
dealing with certificates, web servers or anything.
That's all taken care for you.
And on top of that, all your apps are backed
by worldwide global CDN.
So your apps will remain fast
to all of your users around the world,
and you can also make use of that CDN for caching.
So even for API-based applications
with dynamic responses, you can make use of the CDN
to cache those responses on the edge,
and also as you make changes to your applications,
all of that is rolled out with zero downtime to your users,
and if you push broken code, for example,
there are built-in health checks,
so your app will be automatically rolled back
to the latest known working version,
so your users don't notice any downtime at all.
Now, I've already seen in a couple of talks
about App Platform so far.
So I'm not going to spend too much time
talking about the product itself.
Instead, we're just going to go ahead and drop into a live demo.
So I have this website here. It's just one page.
It's a static HTML file,
and the source for it is on GitHub right here.
So let's go ahead and try deploying it to App Platform.
So I'll go to my control panel and click on create app.
Here, I can select my repos, so I'm going to type in the name.
That's fine for the name of the app.
Amsterdam is fine.
Select my branch, and here,
I have the option to also deploy code changes.
So what this means is that if I have this turned on,
any changes that I made for my main branch,
so any commits that I push to it or any PRs that are merged in,
they will automatically be picked up
by App Platform and deployed for me.
So I'm just going to leave that enabled.
Go ahead and click next. It's fishing for my code.
It's selected that it's a static site and static assets.
That's fine.
I don't need to clear anything here, so I'll just click next.
This is the starter plan for static sites.
That's fine, and we'll launch it.
Okay, and now my website is being built and deployed.
So I'm just going to wait for that to finish, and it's done.
So let's write out.
I can click on this URL
that was assigned to my app, and I see my website.
Just like that, my website is now running on App Platform.
Now, let's try something out.
I'm going to go back to the repo,
go into my index.html file, edit it,
and let's change the title here to hello or something.
Then I'll commit the change to my main branch,
and if I go back into the control panel,
in just a few seconds, you'll see the app platform
has already picked up the changes that I just made,
and it's going to deploy them to my live running site.
It's done, and you can see here the deployment reference
is the commit that I just made.
So if I go back to my website, reload,
and you'll see that the changes took effect.
Awesome.
So let's just deploy the static site to App Platform.
Now, let's go ahead and try something
a little more complicated.
So this time, I have this website.
It's just a landing page for this microblogging platform
that I'm building. It's a Laravel app.
It's running in PHP,
and right now, it's just a single page.
It doesn't use a database or anything,
and the source code for it is on GitHub right here.
So let's go ahead and try to deploy this app on App Platform.
So just like before, we click on create app,
select a repo here, microblogs fine.
Just like before, I'll keep all of this as-is.
Click next, and it's fishing for my code again.
Now, one of my favorite things about App Platform
is this notion of app detection.
So you noticed that previously,
it detected that our website was a static site.
It was just an index.html file, but this time,
it's detected that we have a PHP app that's running.
It's a web service and always running a process
that is publicly accessible to the Internet,
and it's also detected a way for us to run this application.
So it's detected a run command that starts a web server,
and it also uses the public directory by default,
which is a common pattern for Laravel applications.
So with app detection, it can dig into your source code
and figure out exactly what kind of app you have in there,
and based on that information,
it can preconfigure things for you.
You can see it's already done that right here.
Now, this is a good start,
but we do need to define a few environment variables
that Laravel applications expect.
So I'll go ahead and add a few of them.
So we'll set the app environment to production,
and I'll set the application key.
This will choose to encrypt, and what this means
is that the value that I entered in here will be encrypted
when it's stored in the app platform services,
and it will be decrypted
only when it's made accessible to Laravel.
Then, the final environment variable is app URL.
This needs to be the URL where my app will be
publicly accessible once it's up and running.
Now, I don't know that yet, but what I can do
is make use of these bindable environment variables.
So it's kind of like a templating system
for environment variables,
so I can just type in app URL like that,
and this will be replaced with the actual URL
that my app will be accessible on,
once this environment variable is made visible to a variable.
So this is all set.
I can go ahead and create my application now.
So just like before, App Platform is building
our application first.
We can actually click on the details link
and dig into the exact logs of the build process.
So you can see it first installing OJS,
and that's because OJS is
one of the dependencies that my app needs,
and it's installing my node modules.
It's installing PHPs and the extensions that Laravel needs.
It's installing my Composer dependencies.
All right.
So it's finished building, and it's been deployed,
so let's go ahead and check it out,
and we have our landing page.
Okay, so I've also been hard at work
moving out the actual microblogging platform,
and it's now ready to launch.
So I'll go in and merge in my PR that contains all of this work,
and I also need a place to store the posts
that are posted on the microblog.
So let's go ahead and add a database to our application.
So we click on components, create component,
database, and I have two options here.
I can either add a dev database.
Clearly, that's not recommended for production,
but it's particularly fine for this demo,
or I can attach an existing database.
So just stick with the DB name, the dev database.
Both of these looks perfect.
I'll create and attach it.
And now, the database is being provisioned
and attached to my application.
Now, we just need to tell Laravel about this database,
so it knows how to use it.
So I'll go into my microblog, edit the environment variables,
and you'll see that I have this database
URL environment variable here that we didn't have before.
And I actually didn't add this myself.
So when I added the database component,
App Platform automatically added this for me,
and it's set to another type of bindable variable,
and this time, it's referencing a property
of one of the components.
So I went ahead and named the database DB,
and this will be replaced by a connection string
that contains all of the necessary credentials
and information to connect Laravel to my database.
So I actually don't need to make any changes right here.
So I'll click close, and this has already been picked up
by this deployment that's in progress.
So I'm just going to wait for that to be done.
Okay, so it says it's finished deploying.
Let's go ahead and check it out.
I'll go back and refresh, and I get an error.
That's not good.
Let's find what's happening.
So I'll go back to the control panel, go into the logs tab.
These will be the live running logs of my application,
and if I look at the logs, scroll up,
try to figure out what's wrong,
you'll see that I've got this error
here that says undefined table: Relation post does not exist.
This is because the database that I attached
to my app is completely empty,
and my Laravel application expects to have my tables
and everything set up in there.
Now, some people like to run their database
migrations on every deploy, but for now,
I've just decided to run it manually.
So what I can do is go into this console,
and this will drop me into a LiveShell
with my running application,
and I can type in php artisan migrate
passing the first flag because this is production,
and it's migrated my table.
Okay, so now it should work.
I'll go back and try it out, and there we go.
I've got my website.
I can log in, choose a username, and I can write a post.
Now, there's this checkbox here that says attach random photo.
Let's just ignore that for now,
and you'll know why in a few seconds,
but for now, just going to save this post, and it's posted.
Refresh. So there, it's using database.
So everything seems to be working, right?
Laravel is using my Postgres database
that I've attached to it, and it's storing posts in it.
Okay, so now my method is good to go.
I'm going to share it on Twitter, Product Hunt
and all these amazing websites,
and fast-forward a bit, I'm getting so much traffic.
People love my website,
and they're already requesting new features.
So one of the features I've decided to implement
is this feature of attaching random photos to your posts.
So people like to personalize their post a bit,
and I decided that that could be a cool feature to implement.
So when you go ahead and write a post,
you'll see this checkbox that we ignored just a few seconds ago.
So the way I've decided to implement this
is because I'm getting so much traffic,
and I don't want my website to slow down,
I decided to process these random photos in the background.
So when you write a post and choose to attach a photo to it,
what will happen is that the post
will be immediately published, and in the background,
a photo will be downloaded and then attached to it.
And to do that, I needed to use a QueueRunner.
So I decided to use Laravel Horizon for this.
So Laravel Horizon will be a continuously running process
that we'll watch for the new jobs
and schedule them to be processed for me.
So let's go ahead and set that up.
Laravel Horizon needs a Redis database
to store the jobs that it's working on
and also to maintain state and communicate with its workers.
So we'll go into the components tab,
click grade component, database,
and this time, we'll go with an existing database.
I've created a Redis database on my DL account,
so let's just select it here.
And I'm seeing Redis DB, that's fine.
Attach it and now, it's been added to the components
that make up my application.
So I've got the Laravel component,
the Postgres database and now the Redis database.
So now we can set up Horizon itself
and create another component.
This time, choose worker.
Now, worker is a continuously running process
that does not accept HTB connections,
which is pretty much exactly what Horizon is.
So I will choose my repo again, name it Horizon this time.
So now, it's using worker because
I had selected that earlier,
and we need to change our run command
to instead of storing a web server,
we need to store Horizon.
So I can change it to HPR that's in Horizon,
and just like before, we need to add the few environment
variable that Laravel expects.
So you'll see that database zero
was automatically edited for my here.
So I'm going to add in the rest of them.
And we also need to tell Horizon
how to access our Redis database.
I'll add in a Redis URL environment variable,
and just like with the database, I can do Redis DB,
that's the name of the Redis database component,
and then Redis URL.
I've also added these three environment variables:
cache driver, key connection and session driver,
all set to Redis, and these tell Laravel
to use the Redis database for these things.
And finally because I'm downloading
actual photos and image files,
I need somewhere to start those too.
I've decided to use DigitalOcean Spaces
as an object store for those files.
So I just need to give it my Spaces credentials
and connect the information.
So I've got them right here,
and finally, we need to tell Laravel
to actually use Spaces for certain files.
So I'll just set these two variables to Spaces.
Now, one last thing.
Laravel Horizon comes with a web dashboard
that lets you see stats and information about it.
My application takes a Horizon key environment variable
that's set to a password for the dashboard
so that not everyone can access it.
I'm just going to set this to Horizon.
It's not a great password, but it's good enough for this demo.
So let's review our environment variables real quick.
I think I've got everything in here for Horizon to work.
I'll go ahead and create it.
And now, Horizon is added to my growing cluster of components.
So I've got Laravel Horizon in both databases.
Now, all of these environment variables
that we added for Horizon,
we also need to add them to the Laravel component,
and that's because Laravel itself also needs to know
about this space where the files are stored.
It needs to know about the Redis database,
so it can connect to Horizon.
So I'm just going to do that off-camera real quick.
I'm just going to copy and paste everything we've added
to the Horizon component.
Okay, so now I've copied and pasted all of them.
Just save it,
and we're just going to wait for this new deployment
to go out with all of these environment variables
that we just added.
Okay, the deployment is finished.
Let's check it out.
I'll go back, write a new post, and this time,
I'll choose to attack a random photo, save it.
Photo attachment scheduled.
Check in a couple of seconds.
So now, it's downloading the image in the background.
So if I reload, I should see it, and there we go.
I've got a photo attached to my post.
What I can do is also go to the Horizon dashboard,
enter the username and password we set,
and here, we can see some information
and stats about Horizon.
So we can see the number of jobs that were processed,
pending, completed and failed jobs, things like that.
Now, what I think I want to highlight
is this insights tab here.
Now, if you go into it,
you can see that for each of those components that we have,
we can see some insights on the CPU usage, memory usage
and just refer databases and the worker components as well.
So we can keep any eye on these stats to figure out
when we need to scale our application up,
if we have a memory leak somewhere, et cetera.
Now, there's one last thing that I want to do.
This whole time, we've been using this domain
that was assigned to our application to access it,
and I think it's about time for us
to assign a nicer one to it.
So I'm going to to the settings page and under the names,
looks like edit, add to main.
I'll go with blog.chart.fyi, and we'll see that it asks me
to add the CNAME record to my DNS for my domain.
So I'm going to copy it, go to my control panel,
add CNAME for a blog, paste in the value created,
and now, it should be good to go.
So I'll go ahead and edit,
and now, my domain is added to my app.
So it's building it in the background,
and what it's doing here is,
it's setting up the mapping from the domain to my app.
It's setting up the HTTPS certificate
and all of that stuff.
So that should be done in just a few minutes,
and now it's done.
So you'll notice that up here, the URL was changed to use
this new domain that we added.
Let's go ahead and try it out, and there we go.
We've got our app running on this custom domain
that we assigned, all with complete
HTTPS, auto-configured for us by default.
Okay, let's zoom out of it and take a look
at what we've got so far.
First, we decided from a fairly simply
Laravel application that's just had one page,
it didn't use the database or anything,
and we got that up and running on App Platform.
Then, we were ready to launch our microblog,
so we added those features,
and we needed a database to store the post in.
So we spun up a Postgres database
and attached it to our app.
Then, we were ready to launch our application,
and it went so well
because people were asking for new features,
so we added the ability to attach random photos to posts,
and so we added a Horizon QueueRunner in the background,
and we gave it a Redis database to use.
And finally, we connected everything to Spaces,
so we can store those images that we were downloading.
In this whole time, we were enjoying all the benefits
that you would expect from a production-ready platform.
We had automatic HTTPS configured by default.
We had zero downtime upgrades when we were rolling out
all these features to our website.
We were able to look at the logs for application,
check out insights like CPU and memory usage
to see how we're doing on the different components.
So that's it from me. I hope you found this useful
and are really itching to try deploying your first web
application to App Platform.
If so, that would make me incredibly happy.
I'd recommend checking out the sample repos
that we have in the control panel.
So you'll see them when you create a new app.
At the bottom, you'll see a bunch of sample applications
in different programming languages.
So you can check them out
and see how they work on the platform.
They are also all open-source, so you'll find them on GitHub,
on the DigitalOcean account as well.
Thank you very much and enjoy the rest of Deploy.