mirror of https://github.com/docker/docs.git
Add FastAPI example for python docs (#20396)
* Add python docker example based on fastapi app * Add gitignore example in python docs * ✏️ Fix port mapping in docker init section * ♻️ Edit refactor to map container ports from 5000-5001 to 8000-8001 * ✏️ Fix some grammatical structures * 📝 Add some notes about kubernetes stuff
This commit is contained in:
parent
6488f1465e
commit
f092419ca0
|
@ -18,12 +18,12 @@ This section walks you through containerizing and running a Python application.
|
||||||
|
|
||||||
## Get the sample application
|
## Get the sample application
|
||||||
|
|
||||||
The sample application uses the popular [Flask](https://flask.palletsprojects.com/) framework.
|
The sample application uses the popular [FastAPI](https://fastapi.tiangolo.com) framework.
|
||||||
|
|
||||||
Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
Clone the sample application to use with this guide. Open a terminal, change directory to a directory that you want to work in, and run the following command to clone the repository:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ git clone https://github.com/docker/python-docker
|
$ git clone https://github.com/estebanx64/python-docker-example
|
||||||
```
|
```
|
||||||
|
|
||||||
## Initialize Docker assets
|
## Initialize Docker assets
|
||||||
|
@ -35,9 +35,9 @@ feature to help streamline the process, or you can manually create the assets.
|
||||||
{{< tabs >}}
|
{{< tabs >}}
|
||||||
{{< tab name="Use Docker Init" >}}
|
{{< tab name="Use Docker Init" >}}
|
||||||
|
|
||||||
Inside the `python-docker` directory, run the `docker init` command. `docker
|
Inside the `python-docker-example` directory, run the `docker init` command. `docker
|
||||||
init` provides some default configuration, but you'll need to answer a few
|
init` provides some default configuration, but you'll need to answer a few
|
||||||
questions about your application. For example, this application uses Flask to
|
questions about your application. For example, this application uses FastAPI to
|
||||||
run. Refer to the following example to answer the prompts from `docker init` and
|
run. Refer to the following example to answer the prompts from `docker init` and
|
||||||
use the same answers for your prompts.
|
use the same answers for your prompts.
|
||||||
|
|
||||||
|
@ -56,7 +56,66 @@ Let's get started!
|
||||||
? What application platform does your project use? Python
|
? What application platform does your project use? Python
|
||||||
? What version of Python do you want to use? 3.11.4
|
? What version of Python do you want to use? 3.11.4
|
||||||
? What port do you want your app to listen on? 8000
|
? What port do you want your app to listen on? 8000
|
||||||
? What is the command to run your app? python3 -m flask run --host=0.0.0.0 --port=8000
|
? What is the command to run your app? python3 -m uvicorn app:app --host=0.0.0.0 --port=8000
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a file named `.gitignore` with the following contents.
|
||||||
|
|
||||||
|
```text {collapse=true,title=".gitignore"}
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
```
|
```
|
||||||
|
|
||||||
{{< /tab >}}
|
{{< /tab >}}
|
||||||
|
@ -118,7 +177,7 @@ COPY . .
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
# Run the application.
|
# Run the application.
|
||||||
CMD python3 -m flask run --host=0.0.0.0 --port=8000
|
CMD python3 -m uvicorn app:app --host=0.0.0.0 --port=8000
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a file named `compose.yaml` with the following contents.
|
Create a file named `compose.yaml` with the following contents.
|
||||||
|
@ -139,39 +198,6 @@ services:
|
||||||
context: .
|
context: .
|
||||||
ports:
|
ports:
|
||||||
- 8000:8000
|
- 8000:8000
|
||||||
|
|
||||||
# The commented out section below is an example of how to define a PostgreSQL
|
|
||||||
# database that your application can use. `depends_on` tells Docker Compose to
|
|
||||||
# start the database before your application. The `db-data` volume persists the
|
|
||||||
# database data between container restarts. The `db-password` secret is used
|
|
||||||
# to set the database password. You must create `db/password.txt` and add
|
|
||||||
# a password of your choosing to it before running `docker compose up`.
|
|
||||||
# depends_on:
|
|
||||||
# db:
|
|
||||||
# condition: service_healthy
|
|
||||||
# db:
|
|
||||||
# image: postgres
|
|
||||||
# restart: always
|
|
||||||
# user: postgres
|
|
||||||
# secrets:
|
|
||||||
# - db-password
|
|
||||||
# volumes:
|
|
||||||
# - db-data:/var/lib/postgresql/data
|
|
||||||
# environment:
|
|
||||||
# - POSTGRES_DB=example
|
|
||||||
# - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
|
||||||
# expose:
|
|
||||||
# - 5432
|
|
||||||
# healthcheck:
|
|
||||||
# test: [ "CMD", "pg_isready" ]
|
|
||||||
# interval: 10s
|
|
||||||
# timeout: 5s
|
|
||||||
# retries: 5
|
|
||||||
# volumes:
|
|
||||||
# db-data:
|
|
||||||
# secrets:
|
|
||||||
# db-password:
|
|
||||||
# file: db/password.txt
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a file named `.dockerignore` with the following contents.
|
Create a file named `.dockerignore` with the following contents.
|
||||||
|
@ -212,17 +238,77 @@ Create a file named `.dockerignore` with the following contents.
|
||||||
LICENSE
|
LICENSE
|
||||||
README.md
|
README.md
|
||||||
```
|
```
|
||||||
|
Create a file named `.gitignore` with the following contents.
|
||||||
|
|
||||||
|
```text {collapse=true,title=".gitignore"}
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
```
|
||||||
|
|
||||||
{{< /tab >}}
|
{{< /tab >}}
|
||||||
{{< /tabs >}}
|
{{< /tabs >}}
|
||||||
|
|
||||||
You should now have the following contents in your `python-docker`
|
You should now have the following contents in your `python-docker-example`
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
├── python-docker/
|
├── python-docker-example/
|
||||||
│ ├── app.py
|
│ ├── app.py
|
||||||
│ ├── requirements.txt
|
│ ├── requirements.txt
|
||||||
│ ├── .dockerignore
|
│ ├── .dockerignore
|
||||||
|
│ ├── .gitignore
|
||||||
│ ├── compose.yaml
|
│ ├── compose.yaml
|
||||||
│ ├── Dockerfile
|
│ ├── Dockerfile
|
||||||
│ └── README.md
|
│ └── README.md
|
||||||
|
@ -231,25 +317,26 @@ directory.
|
||||||
To learn more about the files, see the following:
|
To learn more about the files, see the following:
|
||||||
- [Dockerfile](../../reference/dockerfile.md)
|
- [Dockerfile](../../reference/dockerfile.md)
|
||||||
- [.dockerignore](../../reference/dockerfile.md#dockerignore-file)
|
- [.dockerignore](../../reference/dockerfile.md#dockerignore-file)
|
||||||
|
- [.gitignore](https://git-scm.com/docs/gitignore)
|
||||||
- [compose.yaml](../../compose/compose-file/_index.md)
|
- [compose.yaml](../../compose/compose-file/_index.md)
|
||||||
|
|
||||||
## Run the application
|
## Run the application
|
||||||
|
|
||||||
Inside the `python-docker` directory, run the following command in a
|
Inside the `python-docker-example` directory, run the following command in a
|
||||||
terminal.
|
terminal.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ docker compose up --build
|
$ docker compose up --build
|
||||||
```
|
```
|
||||||
|
|
||||||
Open a browser and view the application at [http://localhost:8000](http://localhost:8000). You should see a simple Flask application.
|
Open a browser and view the application at [http://localhost:8000](http://localhost:8000). You should see a simple FastAPI application.
|
||||||
|
|
||||||
In the terminal, press `ctrl`+`c` to stop the application.
|
In the terminal, press `ctrl`+`c` to stop the application.
|
||||||
|
|
||||||
### Run the application in the background
|
### Run the application in the background
|
||||||
|
|
||||||
You can run the application detached from the terminal by adding the `-d`
|
You can run the application detached from the terminal by adding the `-d`
|
||||||
option. Inside the `python-docker` directory, run the following command
|
option. Inside the `python-docker-example` directory, run the following command
|
||||||
in a terminal.
|
in a terminal.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
|
@ -258,7 +345,9 @@ $ docker compose up --build -d
|
||||||
|
|
||||||
Open a browser and view the application at [http://localhost:8000](http://localhost:8000).
|
Open a browser and view the application at [http://localhost:8000](http://localhost:8000).
|
||||||
|
|
||||||
You should see a simple Flask application.
|
To see the OpenAPI docs you can go to [http://localhost:8000/docs](http://localhost:8000/docs).
|
||||||
|
|
||||||
|
You should see a simple FastAPI application.
|
||||||
|
|
||||||
In the terminal, run the following command to stop the application.
|
In the terminal, run the following command to stop the application.
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ description: Learn how to develop locally using Kubernetes
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Complete all the previous sections of this guide, starting with [Containerize a Python application](containerize.md).
|
- Complete all the previous sections of this guide, starting with [Use containers for python development](develop.md).
|
||||||
- [Turn on Kubernetes](/desktop/kubernetes/#install-and-turn-on-kubernetes) in Docker Desktop.
|
- [Turn on Kubernetes](/desktop/kubernetes/#install-and-turn-on-kubernetes) in Docker Desktop.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
@ -15,12 +15,85 @@ In this section, you'll learn how to use Docker Desktop to deploy your applicati
|
||||||
|
|
||||||
## Create a Kubernetes YAML file
|
## Create a Kubernetes YAML file
|
||||||
|
|
||||||
In your `python-docker-dev` directory, create a file named
|
In your `python-docker-dev-example` directory, create a file named `docker-postgres-kubernetes.yaml`. Open the file in an IDE or text editor and add
|
||||||
`docker-python-kubernetes.yaml`. Open the file in an IDE or text editor and add
|
|
||||||
the following contents. Replace `DOCKER_USERNAME/REPO_NAME` with your Docker
|
the following contents. Replace `DOCKER_USERNAME/REPO_NAME` with your Docker
|
||||||
username and the name of the repository that you created in [Configure CI/CD for
|
username and the name of the repository that you created in [Configure CI/CD for
|
||||||
your Python application](configure-ci-cd.md).
|
your Python application](configure-ci-cd.md).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: postgres
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: postgres
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: postgres
|
||||||
|
image: postgres
|
||||||
|
ports:
|
||||||
|
- containerPort: 5432
|
||||||
|
env:
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
value: example
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
value: postgres
|
||||||
|
- name: POSTGRES_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
|
volumeMounts:
|
||||||
|
- name: postgres-data
|
||||||
|
mountPath: /var/lib/postgresql/data
|
||||||
|
volumes:
|
||||||
|
- name: postgres-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: postgres-pvc
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: postgres
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 5432
|
||||||
|
selector:
|
||||||
|
app: postgres
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: postgres-pvc
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 1Gi
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: postgres-secret
|
||||||
|
namespace: default
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
POSTGRES_PASSWORD: cG9zdGdyZXNfcGFzc3dvcmQ= # Base64 encoded password (e.g., 'postgres_password')
|
||||||
|
```
|
||||||
|
|
||||||
|
In your `python-docker-dev-example` directory, create a file named `docker-python-kubernetes.yaml`.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
|
@ -31,19 +104,32 @@ spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
service: flask
|
service: fastapi
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
service: flask
|
service: fastapi
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: flask-service
|
- name: fastapi-service
|
||||||
image: DOCKER_USERNAME/REPO_NAME
|
image: technox64/python-docker-dev-example-test:latest
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
env:
|
env:
|
||||||
- name: POSTGRES_PASSWORD
|
- name: POSTGRES_PASSWORD
|
||||||
value: mysecretpassword
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: postgres-secret
|
||||||
|
key: POSTGRES_PASSWORD
|
||||||
|
- name: POSTGRES_USER
|
||||||
|
value: postgres
|
||||||
|
- name: POSTGRES_DB
|
||||||
|
value: example
|
||||||
|
- name: POSTGRES_SERVER
|
||||||
|
value: postgres
|
||||||
|
- name: POSTGRES_PORT
|
||||||
|
value: "5432"
|
||||||
|
ports:
|
||||||
|
- containerPort: 8001
|
||||||
---
|
---
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
|
@ -53,38 +139,60 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
type: NodePort
|
type: NodePort
|
||||||
selector:
|
selector:
|
||||||
service: flask
|
service: fastapi
|
||||||
ports:
|
ports:
|
||||||
- port: 8001
|
- port: 8001
|
||||||
targetPort: 8001
|
targetPort: 8001
|
||||||
nodePort: 30001
|
nodePort: 30001
|
||||||
```
|
```
|
||||||
|
|
||||||
In this Kubernetes YAML file, there are two objects, separated by the `---`:
|
In these Kubernetes YAML file, there are various objects, separated by the `---`:
|
||||||
|
|
||||||
- A Deployment, describing a scalable group of identical pods. In this case,
|
- A Deployment, describing a scalable group of identical pods. In this case,
|
||||||
you'll get just one replica, or copy of your pod. That pod, which is
|
you'll get just one replica, or copy of your pod. That pod, which is
|
||||||
described under `template`, has just one container in it. The
|
described under `template`, has just one container in it. The
|
||||||
container is created from the image built by GitHub Actions in [Configure CI/CD for
|
container is created from the image built by GitHub Actions in [Configure CI/CD for
|
||||||
your Python application](configure-ci-cd.md).
|
your Python application](configure-ci-cd.md).
|
||||||
|
- A Service, which will define how the ports are mapped in the containers.
|
||||||
|
- A PersistentVolumeClaim, to define a storage that will be persistent through restarts for the database.
|
||||||
|
- A Secret, Keeping the database password as a example using secret kubernetes resource.
|
||||||
- A NodePort service, which will route traffic from port 30001 on your host to
|
- A NodePort service, which will route traffic from port 30001 on your host to
|
||||||
port 8001 inside the pods it routes to, allowing you to reach your app
|
port 8001 inside the pods it routes to, allowing you to reach your app
|
||||||
from the network.
|
from the network.
|
||||||
|
|
||||||
To learn more about Kubernetes objects, see the [Kubernetes documentation](https://kubernetes.io/docs/home/).
|
To learn more about Kubernetes objects, see the [Kubernetes documentation](https://kubernetes.io/docs/home/).
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
>
|
||||||
|
> * The `NodePort` service is good for development/testing purposes. For production you should implement an [ingress-controller](https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/).
|
||||||
|
|
||||||
## Deploy and check your application
|
## Deploy and check your application
|
||||||
|
|
||||||
1. In a terminal, navigate to `python-docker-dev` and deploy your application to
|
1. In a terminal, navigate to `python-docker-dev-example` and deploy your database to
|
||||||
Kubernetes.
|
Kubernetes.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ kubectl apply -f docker-python-kubernetes.yaml
|
$ kubectl apply -f docker-postgres-kubernetes.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see output that looks like the following, indicating your Kubernetes objects were created successfully.
|
You should see output that looks like the following, indicating your Kubernetes objects were created successfully.
|
||||||
|
|
||||||
```shell
|
```console
|
||||||
|
deployment.apps/postgres created
|
||||||
|
service/postgres created
|
||||||
|
persistentvolumeclaim/postgres-pvc created
|
||||||
|
secret/postgres-secret created
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, deploy your python application.
|
||||||
|
|
||||||
|
```console
|
||||||
|
kubectl apply -f docker-python-kubernetes.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see output that looks like the following, indicating your Kubernetes objects were created successfully.
|
||||||
|
|
||||||
|
```console
|
||||||
deployment.apps/docker-python-demo created
|
deployment.apps/docker-python-demo created
|
||||||
service/service-entrypoint created
|
service/service-entrypoint created
|
||||||
```
|
```
|
||||||
|
@ -97,9 +205,10 @@ To learn more about Kubernetes objects, see the [Kubernetes documentation](https
|
||||||
|
|
||||||
Your deployment should be listed as follows:
|
Your deployment should be listed as follows:
|
||||||
|
|
||||||
```shell
|
```console
|
||||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||||
docker-python-demo 1/1 1 1 15s
|
docker-python-demo 1/1 1 1 48s
|
||||||
|
postgres 1/1 1 1 2m39s
|
||||||
```
|
```
|
||||||
|
|
||||||
This indicates all one of the pods you asked for in your YAML are up and running. Do the same check for your services.
|
This indicates all one of the pods you asked for in your YAML are up and running. Do the same check for your services.
|
||||||
|
@ -110,13 +219,14 @@ To learn more about Kubernetes objects, see the [Kubernetes documentation](https
|
||||||
|
|
||||||
You should get output like the following.
|
You should get output like the following.
|
||||||
|
|
||||||
```shell
|
```console
|
||||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||||
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23h
|
kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 13h
|
||||||
service-entrypoint NodePort 10.99.128.230 <none> 8001:30001/TCP 75s
|
postgres ClusterIP 10.43.209.25 <none> 5432/TCP 3m10s
|
||||||
|
service-entrypoint NodePort 10.43.67.120 <none> 8001:30001/TCP 79s
|
||||||
```
|
```
|
||||||
|
|
||||||
In addition to the default `kubernetes` service, you can see your `service-entrypoint` service, accepting traffic on port 30001/TCP.
|
In addition to the default `kubernetes` service, you can see your `service-entrypoint` service, accepting traffic on port 30001/TCP and the internal `ClusterIP` `postgres` with the port `5432` open to accept connections from you python app.
|
||||||
|
|
||||||
3. In a terminal, curl the service. Note that a database was not deployed in
|
3. In a terminal, curl the service. Note that a database was not deployed in
|
||||||
this example.
|
this example.
|
||||||
|
@ -126,10 +236,11 @@ To learn more about Kubernetes objects, see the [Kubernetes documentation](https
|
||||||
Hello, Docker!!!
|
Hello, Docker!!!
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Run the following command to tear down your application.
|
4. Run the following commands to tear down your application.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ kubectl delete -f docker-python-kubernetes.yaml
|
$ kubectl delete -f docker-python-kubernetes.yaml
|
||||||
|
$ kubectl delete -f docker-postgres-kubernetes.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
|
@ -22,7 +22,7 @@ You'll need to clone a new repository to get a sample application that includes
|
||||||
1. Change to a directory where you want to clone the repository and run the following command.
|
1. Change to a directory where you want to clone the repository and run the following command.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ git clone https://github.com/docker/python-docker-dev
|
$ git clone https://github.com/estebanx64/python-docker-dev-example
|
||||||
```
|
```
|
||||||
|
|
||||||
2. In the cloned repository's directory, manually create the Docker assets or run `docker init` to create the necessary Docker assets.
|
2. In the cloned repository's directory, manually create the Docker assets or run `docker init` to create the necessary Docker assets.
|
||||||
|
@ -48,7 +48,66 @@ You'll need to clone a new repository to get a sample application that includes
|
||||||
? What application platform does your project use? Python
|
? What application platform does your project use? Python
|
||||||
? What version of Python do you want to use? 3.11.4
|
? What version of Python do you want to use? 3.11.4
|
||||||
? What port do you want your app to listen on? 8001
|
? What port do you want your app to listen on? 8001
|
||||||
? What is the command to run your app? python3 -m flask run --host=0.0.0.0 --port=8001
|
? What is the command to run your app? python3 -m uvicorn app:app --host=0.0.0.0 --port=8001
|
||||||
|
```
|
||||||
|
|
||||||
|
Create a file named `.gitignore` with the following contents.
|
||||||
|
|
||||||
|
```text {collapse=true,title=".gitignore"}
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
```
|
```
|
||||||
|
|
||||||
{{< /tab >}}
|
{{< /tab >}}
|
||||||
|
@ -110,7 +169,7 @@ You'll need to clone a new repository to get a sample application that includes
|
||||||
EXPOSE 8001
|
EXPOSE 8001
|
||||||
|
|
||||||
# Run the application.
|
# Run the application.
|
||||||
CMD python3 -m flask run --host=0.0.0.0 --port=8001
|
CMD python3 -m uvicorn app:app --host=0.0.0.0 --port=8001
|
||||||
```
|
```
|
||||||
|
|
||||||
Create a file named `compose.yaml` with the following contents.
|
Create a file named `compose.yaml` with the following contents.
|
||||||
|
@ -204,6 +263,65 @@ You'll need to clone a new repository to get a sample application that includes
|
||||||
LICENSE
|
LICENSE
|
||||||
README.md
|
README.md
|
||||||
```
|
```
|
||||||
|
Create a file named `.gitignore` with the following contents.
|
||||||
|
|
||||||
|
```text {collapse=true,title=".gitignore"}
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
```
|
||||||
|
|
||||||
{{< /tab >}}
|
{{< /tab >}}
|
||||||
{{< /tabs >}}
|
{{< /tabs >}}
|
||||||
|
|
||||||
|
@ -217,7 +335,7 @@ In the `compose.yaml` file, you need to uncomment all of the database instructio
|
||||||
|
|
||||||
The following is the updated `compose.yaml` file.
|
The following is the updated `compose.yaml` file.
|
||||||
|
|
||||||
```yaml {hl_lines="7-36"}
|
```yaml {hl_lines="7-43"}
|
||||||
services:
|
services:
|
||||||
server:
|
server:
|
||||||
build:
|
build:
|
||||||
|
@ -225,6 +343,9 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- 8001:8001
|
- 8001:8001
|
||||||
environment:
|
environment:
|
||||||
|
- POSTGRES_SERVER=db
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
- POSTGRES_DB=example
|
||||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
|
@ -271,16 +392,18 @@ mysecretpassword
|
||||||
|
|
||||||
Save and close the `password.txt` file.
|
Save and close the `password.txt` file.
|
||||||
|
|
||||||
You should now have the following contents in your `python-docker-dev`
|
You should now have the following contents in your `python-docker-dev-example`
|
||||||
directory.
|
directory.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
├── python-docker-dev/
|
├── python-docker-dev-example/
|
||||||
│ ├── db/
|
│ ├── db/
|
||||||
│ │ └── password.txt
|
│ │ └── password.txt
|
||||||
│ ├── app.py
|
│ ├── app.py
|
||||||
|
│ ├── config.py
|
||||||
│ ├── requirements.txt
|
│ ├── requirements.txt
|
||||||
│ ├── .dockerignore
|
│ ├── .dockerignore
|
||||||
|
│ ├── .gitignore
|
||||||
│ ├── compose.yaml
|
│ ├── compose.yaml
|
||||||
│ ├── Dockerfile
|
│ ├── Dockerfile
|
||||||
│ ├── README.Docker.md
|
│ ├── README.Docker.md
|
||||||
|
@ -295,18 +418,50 @@ $ docker compose up --build
|
||||||
|
|
||||||
Now test your API endpoint. Open a new terminal then make a request to the server using the curl commands:
|
Now test your API endpoint. Open a new terminal then make a request to the server using the curl commands:
|
||||||
|
|
||||||
|
Let's create an object with a post method
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ curl http://localhost:8001/initdb
|
$ curl -X 'POST' \
|
||||||
$ curl http://localhost:8001/widgets
|
'http://0.0.0.0:8001/heroes/' \
|
||||||
|
-H 'accept: application/json' \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{
|
||||||
|
"id": 1,
|
||||||
|
"name": "my hero",
|
||||||
|
"secret_name": "austing",
|
||||||
|
"age": 12
|
||||||
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
You should receive the following response:
|
You should receive the following response:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
[]
|
{
|
||||||
|
"age": 12,
|
||||||
|
"id": 1,
|
||||||
|
"name": "my hero",
|
||||||
|
"secret_name": "austing"
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The response is empty because your database is empty.
|
Let's make a get request with the next curl command:
|
||||||
|
|
||||||
|
```console
|
||||||
|
curl -X 'GET' \
|
||||||
|
'http://0.0.0.0:8001/heroes/' \
|
||||||
|
-H 'accept: application/json'
|
||||||
|
```
|
||||||
|
|
||||||
|
You should receive the same response as above because it's the only one object we have in database.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"age": 12,
|
||||||
|
"id": 1,
|
||||||
|
"name": "my hero",
|
||||||
|
"secret_name": "austing"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Press `ctrl+c` in the terminal to stop your application.
|
Press `ctrl+c` in the terminal to stop your application.
|
||||||
|
|
||||||
|
@ -319,7 +474,7 @@ Watch](../../compose/file-watch.md).
|
||||||
Open your `compose.yaml` file in an IDE or text editor and then add the Compose
|
Open your `compose.yaml` file in an IDE or text editor and then add the Compose
|
||||||
Watch instructions. The following is the updated `compose.yaml` file.
|
Watch instructions. The following is the updated `compose.yaml` file.
|
||||||
|
|
||||||
```yaml {hl_lines="14-17"}
|
```yaml {hl_lines="17-20"}
|
||||||
services:
|
services:
|
||||||
server:
|
server:
|
||||||
build:
|
build:
|
||||||
|
@ -327,6 +482,9 @@ services:
|
||||||
ports:
|
ports:
|
||||||
- 8001:8001
|
- 8001:8001
|
||||||
environment:
|
environment:
|
||||||
|
- POSTGRES_SERVER=db
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
- POSTGRES_DB=example
|
||||||
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
|
@ -377,7 +535,7 @@ Hello, Docker!
|
||||||
|
|
||||||
Any changes to the application's source files on your local machine will now be immediately reflected in the running container.
|
Any changes to the application's source files on your local machine will now be immediately reflected in the running container.
|
||||||
|
|
||||||
Open `python-docker-dev/app.py` in an IDE or text editor and update the `Hello, Docker!` string by adding a few more exclamation marks.
|
Open `python-docker-dev-example/app.py` in an IDE or text editor and update the `Hello, Docker!` string by adding a few more exclamation marks.
|
||||||
|
|
||||||
```diff
|
```diff
|
||||||
- return 'Hello, Docker!'
|
- return 'Hello, Docker!'
|
||||||
|
|
Loading…
Reference in New Issue