♪♪ ♪♪ ♪♪ -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.