Skip to content

Commit

Permalink
Merge pull request #161 from tecladocode/develop
Browse files Browse the repository at this point in the history
A few upgrades and fixes!
  • Loading branch information
jslvtr authored Jun 21, 2024
2 parents d3578a5 + 37e6ff6 commit 1701703
Show file tree
Hide file tree
Showing 304 changed files with 10,789 additions and 16,154 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"githubPullRequests.ignoredPullRequestBranches": [
"develop"
]
}
11 changes: 0 additions & 11 deletions docs/docs/01_course_intro/01_curriculum_overview/README.md

This file was deleted.

3 changes: 2 additions & 1 deletion docs/docs/01_course_intro/02_how_to_install_python/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: How to install Python
description: A brief description of the lecture goes here.
ctslug: how-to-install-python
---

# How to install Python on your computer
Expand All @@ -25,7 +26,7 @@ If you have multiple versions of Python installed, such as a version you install
C:\\Users\\yourname\\AppData\\Local\\Programs\\Python\\Python39-32\\python.exe
```

When you use an IDE, such as [Visual Studio Code](../how_to_install_ide), you can use the integrated terminal instead of `cmd.exe`.
When you use an IDE, such as [Visual Studio Code](../how_to_install_ide/), you can use the integrated terminal instead of `cmd.exe`.

## On Mac

Expand Down
1 change: 1 addition & 0 deletions docs/docs/01_course_intro/03_how_to_install_ide/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: How to install an IDE
description: What IDE should you use? How do you install it? Let me show you in this quick guide.
ctslug: how-to-install-an-ide
---

# How to install an IDE
Expand Down
11 changes: 6 additions & 5 deletions docs/docs/01_course_intro/04_what_is_rest_api/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: "What is a REST API?"
description: "There's a lot of confusion around what is and isn't a REST API. Let's take a look!"
ctslug: what-is-an-rest-api
---

# What is a REST API?
Expand Down Expand Up @@ -151,11 +152,11 @@ We'll deal with user authentication in a later section, but that's what the lock

### Stores

| Method | Endpoint | Description |
| ------ | ------------- | ---------------------------------------- |
| `GET` | `/store` | Get a list of all stores. |
| `POST` | `/store` | Create a store. |
| `GET` | `/store/{id}` | Get a single store, given its unique id. |
| Method | Endpoint | Description |
| -------- | ------------- | ---------------------------------------- |
| `GET` | `/store` | Get a list of all stores. |
| `POST` | `/store` | Create a store. |
| `GET` | `/store/{id}` | Get a single store, given its unique id. |
| `DELETE` | `/store/{id}` | Delete a store, given its unique id. |

### Items
Expand Down
1 change: 1 addition & 0 deletions docs/docs/03_first_rest_api/01_project_overview/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Project Overview
description: A first look at the project we'll build in this section.
ctslug: overview-of-your-first-rest-api
---

# Overview of your first REST API
Expand Down
1 change: 1 addition & 0 deletions docs/docs/03_first_rest_api/02_getting_set_up/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Getting set up
description: Set up a Flask project and create the Flask app.
ctslug: getting-set-up
---

# Getting set up
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Your First REST API Endpoint
description: Learn how to define a REST API endpoint using Flask.
ctslug: your-first-rest-api-endpoint
---

# Your First REST API Endpoint
Expand Down
1 change: 1 addition & 0 deletions docs/docs/03_first_rest_api/04_what_is_json/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: "What is JSON?"
description: JSON is the way we normally transfer data to and from REST APIs.
ctslug: what-is-json
---

# What is JSON?
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: How to interact with your REST API
description: Use Postman and Insomnia REST Client to interact with your REST API.
ctslug: how-to-interact-with-your-rest-api
---

# How to make a request to a REST API
Expand Down Expand Up @@ -28,11 +29,11 @@ Start by [downloading Insomnia REST Client](https://insomnia.rest/).

Once you've opened it, create a Project. I would call it "REST APIs with Flask and Python".

![Creating the Project for this course](assets/creating-project.png)
![Creating the Project for this course](https://res.cloudinary.com/teclado/image/upload/v1689180715/courses/rest-apis-flask-python/creating-project_qsyxlg.png)

Then, create a new Request Collection. Call it "Stores REST API".

![Creating the Stores REST API Request Collection](assets/making-request-collection.png)
![Creating the Stores REST API Request Collection](https://res.cloudinary.com/teclado/image/upload/v1689180710/courses/rest-apis-flask-python/making-request-collection_lcthlv.png)

In the Request Collection, we can now add requests! Each request has a few parts:

Expand All @@ -45,19 +46,19 @@ Let's create our first request, `GET /store`.

Make a new request using the Insomnia interface. First, use the dropdown to start:

![How to make a request using the Insomnia interface](assets/making-request.png)
![How to make a request using the Insomnia interface](https://res.cloudinary.com/teclado/image/upload/v1689180711/courses/rest-apis-flask-python/making-request_hmiptl.png)

Then enter the request name. Leave the method as `GET`:

![Enter the request name and method](assets/set-request-name-and-method.png)
![Enter the request name and method](https://res.cloudinary.com/teclado/image/upload/v1689180712/courses/rest-apis-flask-python/set-request-name-and-method_bc6smy.png)

Once you're done, you will see your request in the collection:

![The request is shown in the collection](assets/before-setting-url.png)
![The request is shown in the collection](https://res.cloudinary.com/teclado/image/upload/v1689180711/courses/rest-apis-flask-python/before-setting-url_qjxvyr.png)

Next up, enter the URL for your request. Here we will be requesting the `/store` endpoint. Remember to include your Base URL as well:

![Entering the full URL for the request in Insomnia](assets/url-set.png)
![Entering the full URL for the request in Insomnia](https://res.cloudinary.com/teclado/image/upload/v1689180714/courses/rest-apis-flask-python/url-set_fgp9s9.png)

Once you're done, make sure that your Flask app is running! If it isn't, remember to activate your virtual environment first and then run the app:

Expand All @@ -74,6 +75,6 @@ If you get an error, read it carefully and make sure that no other Flask app is

Once your Flask app is running, you can hit "Send" on the Insomnia client, and you should see the JSON come back from your API!

![Making a request to our API using Insomnia](assets/after-pressing-send.png)
![Making a request to our API using Insomnia](https://res.cloudinary.com/teclado/image/upload/v1689180712/courses/rest-apis-flask-python/after-pressing-send_okjkjq.png)

If that worked and you can see your JSON, you're good to go! You've made your first API request. Now we can continue developing our REST API, remembering to always create new Requests in Insomnia and test our code as we go along!
1 change: 1 addition & 0 deletions docs/docs/03_first_rest_api/06_creating_stores/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: How to create stores
description: Learn how to add data to our REST API.
ctslug: how-to-create-stores
---

# How to create stores in our REST API
Expand Down
1 change: 1 addition & 0 deletions docs/docs/03_first_rest_api/07_creating_items/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: How to create items in each store
description: A brief description of the lecture goes here.
ctslug: how-to-create-items-in-each-store
---

# How to create items in our REST API
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Get a specific store and its items
description: How to use Flask to return data from your REST API to your client.
ctslug: get-a-specific-store-and-its-items
---

# How to get a specific store and its items
Expand Down
1 change: 1 addition & 0 deletions docs/docs/03_first_rest_api/09_final_code/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
---
title: Final code of this section
description: Overview of the project we've built and all the code in it.
ctslug: final-code-of-this-section
---

# Final code of this section
Expand Down
84 changes: 80 additions & 4 deletions docs/docs/04_docker_intro/01_what_is_docker_container/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# What is a Docker container?
---
ctslug: what-is-a-docker-container
description: Learn what Docker images and containers are, and how we can use them to distribute and run our applications.
---

# What are Docker images and containers?

I'm sure you have heard of the term "Virtual Machine". A virtual machine is an emulation of an Operating System. For example, if you run a Windows virtual machine on your MacOS computer, it will run a whole copy of Windows so you can run Windows programs.

This diagram shows what happens in that case:

![Virtual Machine Diagram stack](./assets/vm.drawio.png)
![Virtual Machine Diagram stack](https://res.cloudinary.com/teclado/image/upload/v1689180716/courses/rest-apis-flask-python/vm.drawio_nlrxmx.png)

When you run a Virtual Machine, you can configure what hardware it has access to (e.g. 50% of the host's RAM, 2 CPU cores, etc).

Expand All @@ -14,7 +19,7 @@ Containers have their own storage and networking, but because they don't have to

This diagram shows how Linux containers run in a Linux host:

![Docker Diagram stack](./assets/docker-linux.drawio.png)
![Docker Diagram stack](https://res.cloudinary.com/teclado/image/upload/v1689180716/courses/rest-apis-flask-python/docker-linux.drawio_ebvff5.png)

Looks similar, but the `docker -> container` section is much more efficient than running a VM because it **uses the host's kernel** instead of running its own.

Expand Down Expand Up @@ -85,4 +90,75 @@ Yes!
When we build our Docker image, we will be building it _on top of_ other, pre-built, existing images. Those images come with the lower-level requirements such as compilers, the C language, and most utilities and programs we need.
:::

Let's take a look at Docker images in the next lecture.
## What is a Docker image?

A Docker image is a snapshot of source code, libraries, dependencies, tools, and everything else (except the Operating System kernel!) that a container needs to run.

There are many pre-built images that you can use. For example, some come with Ubuntu (a Linux distribution). Others come with Ubuntu and Python already installed. You can also make your own images that already have Flask installed (as well as other dependencies your app needs).

:::info Comes with Ubuntu?
In the last lecture I mentioned that Docker containers use the host OS kernel, so why does the container need Ubuntu?

Remember that operating systems are kernel + programs/libraries. Although the container uses the host kernel, we may still need a lot of programs/libraries that Ubuntu ships with. An example might be a C language compiler!
:::

This is how you define a Docker image. I'll guide you through how to do this in the next lecture, but bear with me for a second:

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

This is a `Dockerfile`, a definition of how to create a Docker image. Once you have this file, you can ask Docker to create the Docker image. Then, after creating the Docker image, you can ask Docker to run it as a container.

```
Dockerfile ---build--> docker image ---run--> docker container
```

In this `Dockerfile` you can see the first line: `FROM python:3.10`. This tells Docker to first download the `python:3.10` image (an image someone else already created), and once that image is created, run the following commands.

:::info What's in the Python image?
The `python:3.10` image is also built using a `Dockerfile`! You can see the `Dockerfile` for it [here](https://github.com/docker-library/python/blob/master/3.10/bookworm/Dockerfile).

You can see it comes `FROM` another image. There is usually a chain of these, images built upon other images, until you reach the base image. In this case, the [base image](https://github.com/docker-library/buildpack-deps/blob/master/debian/bookworm/Dockerfile) is running Debian (a Linux distribution).

<details>
<summary>Where is the base image!?</summary>
<div>
<div>

If you really want to go deep, you will be able to find...

- The [`python3.10:bookworm`](https://github.com/docker-library/python/blob/master/3.10/bookworm/Dockerfile) image builds on `buildpack-deps:bookworm`
- [`buildpack-deps:bookworm`](https://github.com/docker-library/buildpack-deps/blob/master/debian/bookworm/Dockerfile) builds on `buildpack-deps:bookworm-scm`
- [`buildpack-deps:bookworm-scm`](https://github.com/docker-library/buildpack-deps/blob/master/debian/bookworm/scm/Dockerfile) builds on `buildpack-deps:bookworm-curl`
- [`buildpack-deps:bookworm-curl`](https://github.com/docker-library/buildpack-deps/blob/master/debian/bookworm/curl/Dockerfile) builds on `debian:bookworm`
- [`debian:bookworm`](https://github.com/debuerreotype/docker-debian-artifacts/blob/f7257ef5b83f6b64385edddeae2d2ba7d1b34935/bookworm/Dockerfile) looks really weird!

Eventually, the base image has to physically include the files that make up the operating system. In that last image, that's the Debian OS files that the maintainers have deemed necessary for the `bookworm` image.

</div>
</div>
</details>

So, why the chain?

Three main reasons:

1. So you don't have to write a super long and complex `Dockerfile` which contains everything you need.
2. So pre-published images can be shared online, and all you have to do is download them.
3. So when your own images use the same base image, Docker in your computer only downloads the base image once, saving you a lot of disk space.
:::

Back to our `Dockerfile`. The commands after `FROM...` are specific to our use case, and do things like install requirements, copy our source code into the image, and tell Docker what command to run when we start a container from this image.

This separation between images and containers is interesting because once the image is created you can ship it across the internet and:

- Share it with other developers.
- Deploy it to servers.

Plus once you've downloaded the image (which can take a while), starting a container from it is almost instant since there's very little work to do.
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
---
ctslug: how-to-run-a-docker-container
description: Learn how to run a Docker container with your REST API using Docker Desktop.
---

# How to run a Docker container

## Install Docker Desktop
Expand Down Expand Up @@ -122,6 +127,6 @@ docker run -dp 5001:5000 rest-apis-flask-python

Try making requests using the URL `127.0.0.1:5000` with Insomnia REST Client or Postman, and you should see it working well!

![Insomnia REST Client successfully made a request to the API running in Docker](assets/running-app-docker.png)
![Insomnia REST Client successfully made a request to the API running in Docker](https://res.cloudinary.com/teclado/image/upload/v1689180719/courses/rest-apis-flask-python/running-app-docker_mkosjm.png)

[^1]: [Docker `EXPOSE` command (Official Documentation)](https://docs.docker.com/engine/reference/builder/#expose)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM python:3.10
EXPOSE 5000
WORKDIR /app
RUN pip install flask
COPY . .
CMD ["flask", "run", "--host", "0.0.0.0"]
45 changes: 45 additions & 0 deletions docs/docs/04_docker_intro/02_run_docker_container/end/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from flask import Flask, request

app = Flask(__name__)

stores = [{"name": "My Store", "items": [{"name": "Chair", "price": 15.99}]}]


@app.get("/store")
def get_stores():
return {"stores": stores}


@app.post("/store")
def create_store():
request_data = request.get_json()
new_store = {"name": request_data["name"], "items": []}
stores.append(new_store)
return new_store, 201


@app.post("/store/<string:name>/item")
def create_item(name):
request_data = request.get_json()
for store in stores:
if store["name"] == name:
new_item = {"name": request_data["name"], "price": request_data["price"]}
store["items"].append(new_item)
return new_item, 201
return {"message": "Store not found"}, 404


@app.get("/store/<string:name>")
def get_store(name):
for store in stores:
if store["name"] == name:
return store
return {"message": "Store not found"}, 404


@app.get("/store/<string:name>/item")
def get_item_in_store(name):
for store in stores:
if store["name"] == name:
return {"items": store["items"]}
return {"message": "Store not found"}, 404
Loading

0 comments on commit 1701703

Please sign in to comment.