Skip to content

Commit

Permalink
Merge pull request #62 from tecladocode/jose/cou-99-write-rendercom-d…
Browse files Browse the repository at this point in the history
…eployments-section
  • Loading branch information
jslvtr authored Sep 23, 2022
2 parents 978213c + d0bb585 commit 7785010
Show file tree
Hide file tree
Showing 19 changed files with 522 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ __pycache__/
*.db
.DS_Store
venv/
.venv/
.venv/
docs/docs/.nota/config.ini

This file was deleted.

1 change: 0 additions & 1 deletion docs/docs-upcoming/10_deploy_to_render/README.md

This file was deleted.

13 changes: 13 additions & 0 deletions docs/docs/11_deploy_to_render/01_section_overview/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Overview of this section

In this section, we will figure out how to get our Flask app and put it on a public server so other people can interact with it! This is called "deploying".

There are many services we can use to deploy our app. Most of them have some sort of "free tier" so that you can try the deployment without having to pay anything. Usually, if you want better performance or unlimited usage, you have to pay.

Remember that just as we run the Flask app in our computers, when we deploy it the app runs in a server, somewhere in the world. For all intents and purposes, the server is just like our computer!

Servers usually run Linux, so we can deploy our Docker images without a performance hit as we would using Mac or Windows.

At the end of the section, you'll be able to access your API using a URL such as [https://rest-api-smorest-docker.onrender.com](https://rest-api-smorest-docker.onrender.com).

For this section, our deployment will be completely free. We will deploy our Flask app for free, and we will also get a free PostgreSQL database on the cloud using ElephantSQL.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Creating a Render.com web service

Let's start by going to [https://render.com](https://render.com) and signing up to an account. You can "Log in with GitHub" to make things easier.

Once you've logged in, you'll see in your [Dashboard](https://dashboard.render.com/services) that you can create a new service using a button at the top right of the page.

Click it, and select "Web Service".

Options other than "Web Service" are useful for different kinds of applications, and some are databases that you can use (but not for free, so we won't use Render for our database in this section).

Then you'll [connect your GitHub account](https://render.com/docs/github) if you haven't already, and look for your repositories.

Select the repository that you created during this course:

![Render.com screenshot showing how to search for and select a repository to connect to from GitHub](./assets/render-github-connect.png)

Then, give it a name and make sure the configuration is as follows:

![Render.com screenshot showing the web service configuration](./assets/render-service-config.png)

- Make sure "Docker" is selected.
- Select a server location close to you. I'm near Frankfurt, but if you are in the US or Asia you might want to choose a different one so it's faster to connect to.
- Select the "Free" server option.

At the bottom of the service there is an "Advanced" section which you can use to further configure your service. We'll talk more about that in a bit.

For now, hit "Create Web Service" and wait for it to deploy your code from GitHub!

If you navigate to your Dashboard and then click through to your newly created service, you'll be able to see the service details. If it isn't already deploying, click on the "Manual Deploy" button on the top right to initiate a deploy of the latest commit:

![](./assets/deploy-latest-commit.png)

Then you should start seeing logs appear detailing the deployment process!

![](./assets/render-deploy-screen.png)

While on the free plan, deployments are a bit slow. It has to build your image and run it! Give it a few minutes, until the deployment succeeds. You should see this:

![](./assets/render-deploy-finished.png)

Now, you can access your service URL and try it out using Insomnia or Postman!

![](./assets/insomnia-test-prod.png)

:::warning
Free services in Render.com shut down after inactivity for a few minutes. If you don't use your service for a few minutes, it will shut down and it will need to restart, which can take a minute! This is one of the limitations of their free plan.
:::
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
70 changes: 70 additions & 0 deletions docs/docs/11_deploy_to_render/03_docker_with_gunicorn/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Run our Flask app with gunicorn in Docker

Throughout the course, we've been working with a Docker image like this one:

```dockerfile
FROM python:3.10
EXPOSE 5000
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["flask", "run", "--host", "0.0.0.0"]
```

This is all well and good for local development, but when we deploy our application we want to run it with the best performance possible.

This is why we don't want to run the Flask development server and the Flask debugger. Instead, we'll use gunicorn to run our app.

## Run our Flask app with gunicorn

First let's add `gunicorn` to our `requirements.txt` file:

```text title="requirements.txt"
flask
flask-smorest
python-dotenv
sqlalchemy
flask-sqlalchemy
flask-jwt-extended
passlib
flask-migrate
# highlight-start
gunicorn
# highlight-end
```

Then, let's change our `Dockerfile` to use `gunicorn`:

```dockerfile
FROM python:3.10
WORKDIR /app
COPY ./requirements.txt requirements.txt
# highlight-start
RUN pip install --no-cache-dir --upgrade -r requirements.txt
# highlight-end
COPY . .
# highlight-start
CMD ["gunicorn", "--bind", "0.0.0.0:80", "app:create_app()"]
# highlight-end
```

The `CMD` line change is the important one, as it runs `gunicorn` on port `80`, and we pass in the app factory function.

:::tip
Note I've also changed the `pip install` line. Adding `--no-cache-dir` and `--upgrade` just makes sure we can't accidentally install from a cache directory (which shouldn't exist anyway!), and that we'll upgrade to the latest possible versions allowed by our `requirements.txt` file.
:::

## Run the Docker container locally with the Flask development server and debugger

If you use this `Dockerfile`, it doesn't mean you can't run it locally using the Flask development server. You don't have to lose the automatic restarting capabilities, or the Flask debugger.

To run the Docker container locally, you'll have to do this from now on:

```zsh
docker run -dp 5000:5000 -w /app -v "$(pwd):/app" teclado-site-flask sh -c "flask run"
```

This is similar to how we've ran the Docker container with our local code as a volume (that's what `-w /app -v "$(pwd):/app"` does), but at the end of the command we're telling the container to run `flask run` instead of the `CMD` line of the `Dockerfile`. That's what `sh -c "flask run"` does!

Now you're ready to commit and push this to your repository and re-deploy to Render.com!
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# How to get a deployed PostgreSQL database for our app

There are many PostgreSQL-as-a-Service providers (that means, services that handle creating and maintaining your database for you).

Render.com offers PostgreSQL, and the pricing is actually quite fair. However, the free tier is limited and you can only use it for a certain amount of time.

That's why I recommend using ElephantSQL for your free PostgreSQL needs. When you go over the free ElephantSQL limits, then you can use the Render.com database instead.

To get a free ElephantSQL PostgreSQL database, just go to their site, sign up, and then create a database in a region close to your Render.com server. Make sure to select the free tier.

![ElephantSQL screenshot showing plan configuration of Tiny Turtle (free) and name](./assets/select-plan-and-name-elephantsql.png)

Once you've got this, you should be able to see the Database URL:

![ElephantSQL screenshot showing that a copy icon beside the Database URL can be clicked to copy it](./assets/copy-elephantsql-url.png)

Copy this, as you'll need it in the next lecture!
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

1 comment on commit 7785010

@vercel
Copy link

@vercel vercel bot commented on 7785010 Sep 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.