Skip to content

A few upgrades and fixes! #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 57 commits into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
32e0264
Dockerfile update to fix database issue on render.com
teksaver Jun 3, 2023
6ab13de
slugs added to each lecture
Teclado-Jennifer Jul 11, 2023
29b5bb4
build(deps): bump semver from 5.7.1 to 5.7.2 in /docs
dependabot[bot] Jul 12, 2023
ebcc137
Remove empty line before slug in lecture YAML, and remove one duplica…
jslvtr Jul 12, 2023
a73eb73
Rename slug key to ctslug so it doesn't interfere with ebook
jslvtr Jul 12, 2023
c2f5bf9
Merge pull request #138 from tecladocode/add-lecture-slugs-contentful
jslvtr Jul 12, 2023
9a0fe8d
Add missing slugs to 4 lectures
jslvtr Jul 12, 2023
a3cb1cb
Rename just added slugs to ctslug
jslvtr Jul 12, 2023
6736b77
Remove curriculum overview lecture since it isn't used
jslvtr Jul 12, 2023
bb89653
Use Cloudinary for images so that content can be uploaded to teclado.ocm
jslvtr Jul 12, 2023
7c2c006
Add -webkit and -moz prefixes to background-clip so text renders prop…
jslvtr Aug 13, 2023
58398dc
Merge pull request #139 from tecladocode/jose/cou-322-fix-text-buying…
jslvtr Aug 13, 2023
aad7d91
build(deps): bump postcss from 8.4.16 to 8.4.31 in /docs
dependabot[bot] Oct 7, 2023
a7c8e1b
Update `buster` to `bookworm`
jslvtr Oct 24, 2023
f526a16
Merge pull request #142 from tecladocode/jose/update-buster-to-bookworm
jslvtr Oct 24, 2023
967bdc5
Updated code and ebook to match lecture video, see COU 321
LUS24 Nov 3, 2023
bcb9356
Merge pull request #143 from LUS24/leospairani/cou-321-mistmatch-betw…
jslvtr Nov 3, 2023
5399dfa
Updated files to match lecture videos, see COU-300
LUS24 Nov 4, 2023
cb188bc
Updated file names according to COU-300
LUS24 Nov 6, 2023
ce1c112
Merge pull request #144 from LUS24/leospairani/cou-300-section-12-lec…
jslvtr Nov 8, 2023
e9d50e1
Remove db creation
LUS24 Feb 8, 2024
3931475
Added missing import on section 06
LUS24 Mar 19, 2024
d008e89
Merge pull request #146 from LUS24/develop
jslvtr Mar 19, 2024
998635f
Merge pull request #145 from LUS24/leospairani/cou-334-investigate-re…
jslvtr Apr 4, 2024
ec3090b
Merge branch 'develop' into patch-1
jslvtr Apr 4, 2024
8f27b58
Merge pull request #136 from teksaver/patch-1
jslvtr Apr 4, 2024
5d7c7a7
Merge pull request #137 from tecladocode/dependabot/npm_and_yarn/docs…
jslvtr Apr 4, 2024
14e8a2f
Merge pull request #141 from tecladocode/dependabot/npm_and_yarn/docs…
jslvtr Apr 4, 2024
5f0e077
build(deps): bump @babel/traverse from 7.19.3 to 7.24.1 in /docs
dependabot[bot] Apr 4, 2024
a6a4267
build(deps): bump express from 4.18.1 to 4.19.2 in /docs
dependabot[bot] Apr 4, 2024
fda32fe
build(deps): bump webpack-dev-middleware from 5.3.3 to 5.3.4 in /docs
dependabot[bot] Apr 4, 2024
6502c2a
build(deps): bump follow-redirects from 1.14.9 to 1.15.6 in /docs
dependabot[bot] Apr 4, 2024
8de4d61
Merge pull request #148 from tecladocode/dependabot/npm_and_yarn/docs…
jslvtr Apr 4, 2024
31cc0f1
Merge pull request #149 from tecladocode/dependabot/npm_and_yarn/docs…
jslvtr Apr 4, 2024
00d0c61
Merge pull request #150 from tecladocode/dependabot/npm_and_yarn/docs…
jslvtr Apr 4, 2024
b04aec7
Merge pull request #151 from tecladocode/dependabot/npm_and_yarn/docs…
jslvtr Apr 4, 2024
69061e8
build(deps): bump the npm_and_yarn group in /docs with 3 updates
dependabot[bot] Apr 4, 2024
f817f50
Merge pull request #155 from tecladocode/dependabot/npm_and_yarn/docs…
jslvtr Apr 4, 2024
a1baec9
🐛 fix(Alembic): Remove `compare_type` references
jslvtr Apr 4, 2024
c4768ad
🚸 ux(Lecture code): Add missing start/end lecture codes in 04_02
jslvtr Apr 4, 2024
fbc9a81
✨ feat(Docker compose): Add Docker compose lectures
jslvtr Apr 4, 2024
9ba7bb6
Remove `-` from docker compose command
jslvtr Apr 4, 2024
ad4f496
🐛 fix(Indentation): Fix indentation in `env.py`
jslvtr Apr 4, 2024
369e132
🐛 fix(JS): Fix VideoEmbed component allowfullscreen
jslvtr Apr 4, 2024
a3b2d2f
Merge pull request #147 from tecladocode/jose/cou-323-add-information…
jslvtr Apr 4, 2024
c837700
📦️ dep-up(JS): Update JS dependencies for Docusaurus 3.2
jslvtr Apr 4, 2024
69a5e36
🐛 fix(Prism): Update usage of prism-react-renderer
jslvtr Apr 4, 2024
2fd689b
Merge pull request #156 from tecladocode/jose/fix-js-deps
jslvtr Apr 4, 2024
19366be
🐛 fix(Item Update): Fix `ItemUpdateSchema` by adding `store_id`
jslvtr Apr 5, 2024
6fcf0cc
Merge pull request #157 from tecladocode/jose/cou-332-fix-code-mismat…
jslvtr Apr 5, 2024
2c4b75a
Update README.md
flyingearl Apr 23, 2024
e61e678
Removed version key from docker-compose.yml and docs
LUS24 May 23, 2024
ed92dab
Merge pull request #158 from flyingearl/fix-missing-import
jslvtr May 23, 2024
49a3a7b
feat(compose): add new lecture on running commands in a container
jslvtr Jun 21, 2024
685e8bf
feat(compose): add info on healthchecks and depends_on conditions
jslvtr Jun 21, 2024
ec5d3b4
Merge pull request #160 from tecladocode/jose/cou-537-cover-running-c…
jslvtr Jun 21, 2024
37e6ff6
Merge pull request #159 from LUS24/leospairani/cou-525-docker-compose…
jslvtr Jun 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
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
Loading