Utiliser des conteneurs pour le développement Python
Prérequis
Terminez Conteneuriser une application Python.
Aperçu
Dans cette section, vous apprendrez à mettre en place un environnement de développement pour votre application conteneurisée. Cela inclut :
- L'ajout d'une base de données locale et la persistance des données
- La configuration de Compose pour mettre à jour automatiquement vos services Compose en cours d'exécution lorsque vous modifiez et enregistrez votre code
Obtenir l'application exemple
Vous devrez cloner un nouveau dépôt pour obtenir une application exemple qui inclut la logique de connexion à la base de données.
-
Placez-vous dans un répertoire où vous souhaitez cloner le dépôt et exécutez la commande suivante.
$ git clone https://github.com/estebanx64/python-docker-dev-example
-
Dans le répertoire du dépôt cloné, créez manuellement les ressources Docker ou exécutez
docker init
pour créer les ressources Docker nécessaires.Dans le répertoire du dépôt cloné, exécutez `docker init`. Référez-vous à l'exemple suivant pour répondre aux invites de `docker init`. ```console $ docker init Bienvenue dans le CLI Docker Init ! Cet utilitaire vous guidera dans la création des fichiers suivants avec des valeurs par défaut pertinentes pour votre projet : - .dockerignore - Dockerfile - compose.yaml - README.Docker.md Commençons ! ? Quelle plateforme d'application votre projet utilise-t-il ? Python ? Quelle version de Python voulez-vous utiliser ? 3.11.4 ? Sur quel port voulez-vous que votre application écoute ? 8001 ? Quelle est la commande pour exécuter votre application ? python3 -m uvicorn app:app --host=0.0.0.0 --port=8001 ``` Créez un fichier nommé `.gitignore` avec le contenu suivant. ```text {collapse=true,title=".gitignore"} # Fichiers compilés en byte-code / optimisés / DLL __pycache__/ *.py[cod] *$py.class # Extensions C *.so # Distribution / empaquetage .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # Rapports de test unitaire / couverture htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ cover/ # PEP 582 ; utilisé par ex. github.com/David-OConnor/pyflow et github.com/pdm-project/pdm __pypackages__/ # Environnements .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ ```
Si vous n'avez pas Docker Desktop d'installé ou si vous préférez créer les ressources manuellement, vous pouvez créer les fichiers suivants dans le répertoire de votre projet. Créez un fichier nommé `Dockerfile` avec le contenu suivant. ```dockerfile {collapse=true,title=Dockerfile} # syntax=docker/dockerfile:1 # Des commentaires sont fournis tout au long de ce fichier pour vous aider à démarrer. # Si vous avez besoin de plus d'aide, consultez le guide de référence Dockerfile à l'adresse # https://docs.docker.com/go/dockerfile-reference/ # Vous voulez nous aider à améliorer ce modèle ? Partagez vos commentaires ici : https://forms.gle/ybq9Krt8jtBL3iCk7 ARG PYTHON_VERSION=3.11.4 FROM python:${PYTHON_VERSION}-slim as base # Empêche Python d'écrire des fichiers pyc. ENV PYTHONDONTWRITEBYTECODE=1 # Empêche Python de mettre en mémoire tampon stdout et stderr pour éviter les situations où # l'application plante sans émettre de journaux en raison de la mise en mémoire tampon. ENV PYTHONUNBUFFERED=1 WORKDIR /app # Crée un utilisateur non privilégié sous lequel l'application s'exécutera. # Voir https://docs.docker.com/go/dockerfile-user-best-practices/ ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ --home "/nonexistent" \ --shell "/sbin/nologin" \ --no-create-home \ --uid "${UID}" \ appuser # Télécharge les dépendances dans une étape séparée pour profiter de la mise en cache de Docker. # Utilise un montage de cache sur /root/.cache/pip pour accélérer les constructions ultérieures. # Utilise un montage bind sur requirements.txt pour éviter d'avoir à les copier dans # cette couche. RUN --mount=type=cache,target=/root/.cache/pip \ --mount=type=bind,source=requirements.txt,target=requirements.txt \ python -m pip install -r requirements.txt # Passe à l'utilisateur non privilégié pour exécuter l'application. USER appuser # Copie le code source dans le conteneur. COPY . . # Expose le port sur lequel l'application écoute. EXPOSE 8001 # Exécute l'application. CMD python3 -m uvicorn app:app --host=0.0.0.0 --port=8001 ``` Créez un fichier nommé `compose.yaml` avec le contenu suivant. ```yaml {collapse=true,title=compose.yaml} # Des commentaires sont fournis tout au long de ce fichier pour vous aider à démarrer. # Si vous avez besoin de plus d'aide, consultez le guide de référence de Docker Compose à l'adresse # https://docs.docker.com/go/compose-spec-reference/ # Ici, les instructions définissent votre application comme un service appelé "server". # Ce service est construit à partir du Dockerfile dans le répertoire courant. # Vous pouvez ajouter d'autres services dont votre application peut dépendre ici, comme une # base de données ou un cache. Pour des exemples, consultez le dépôt Awesome Compose : # https://github.com/docker/awesome-compose services: server: build: context: . ports: - 8001:8001 # La section commentée ci-dessous est un exemple de la façon de définir une base de données PostgreSQL # que votre application peut utiliser. `depends_on` indique à Docker Compose de # démarrer la base de données avant votre application. Le volume `db-data` persiste les # données de la base de données entre les redémarrages des conteneurs. Le secret `db-password` est utilisé # pour définir le mot de passe de la base de données. Vous devez créer `db/password.txt` et y ajouter # un mot de passe de votre choix avant d'exécuter `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 ``` Créez un fichier nommé `.dockerignore` avec le contenu suivant. ```text {collapse=true,title=".dockerignore"} # Incluez ici tous les fichiers ou répertoires que vous ne voulez pas copier dans votre # conteneur (par exemple, les artefacts de construction locaux, les fichiers temporaires, etc.). # # Pour plus d'aide, consultez le guide de référence du fichier .dockerignore à l'adresse # https://docs.docker.com/go/build-context-dockerignore/ **/.DS_Store **/__pycache__ **/.venv **/.classpath **/.dockerignore **/.env **/.git **/.gitignore **/.project **/.settings ```
Add a local database and persist data
You can use containers to set up local services, like a database. In this section, you'll update the compose.yaml
file to define a database service and a volume to persist data.
In the cloned repository's directory, open the compose.yaml
file in an IDE or text editor. docker init
handled creating most of the instructions, but you'll need to update it for your unique application.
In the compose.yaml
file, you need to uncomment all of the database instructions. In addition, you need to add the database password file as an environment variable to the server service and specify the secret file to use .
The following is the updated compose.yaml
file.
services:
server:
build:
context: .
ports:
- 8001:8001
environment:
- POSTGRES_SERVER=db
- POSTGRES_USER=postgres
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
depends_on:
db:
condition: service_healthy
secrets:
- db-password
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
NoteTo learn more about the instructions in the Compose file, see Compose file reference.
Before you run the application using Compose, notice that this Compose file specifies a password.txt
file to hold the database's password. You must create this file as it's not included in the source repository.
In the cloned repository's directory, create a new directory named db
and inside that directory create a file named password.txt
that contains the password for the database. Using your favorite IDE or text editor, add the following contents to the password.txt
file.
mysecretpassword
Save and close the password.txt
file.
You should now have the following contents in your python-docker-dev-example
directory.
├── python-docker-dev-example/
│ ├── db/
│ │ └── password.txt
│ ├── app.py
│ ├── config.py
│ ├── requirements.txt
│ ├── .dockerignore
│ ├── .gitignore
│ ├── compose.yaml
│ ├── Dockerfile
│ ├── README.Docker.md
│ └── README.md
Now, run the following docker compose up
command to start your application.
$ docker compose up --build
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
$ curl -X 'POST' \
'http://localhost: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:
{
"age": 12,
"id": 1,
"name": "my hero",
"secret_name": "austing"
}
Let's make a get request with the next curl command:
curl -X 'GET' \
'http://localhost: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.
{
"age": 12,
"id": 1,
"name": "my hero",
"secret_name": "austing"
}
Press ctrl+c
in the terminal to stop your application.
Automatically update services
Use Compose Watch to automatically update your running Compose services as you edit and save your code. For more details about Compose Watch, see Use Compose Watch.
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.
services:
server:
build:
context: .
ports:
- 8001:8001
environment:
- POSTGRES_SERVER=db
- POSTGRES_USER=postgres
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
depends_on:
db:
condition: service_healthy
secrets:
- db-password
develop:
watch:
- action: rebuild
path: .
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
Run the following command to run your application with Compose Watch.
$ docker compose watch
In a terminal, curl the application to get a response.
$ curl http://localhost:8001
Hello, Docker!
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-example/app.py
in an IDE or text editor and update the Hello, Docker!
string by adding a few more exclamation marks.
- return 'Hello, Docker!'
+ return 'Hello, Docker!!!'
Save the changes to app.py
and then wait a few seconds for the application to rebuild. Curl the application again and verify that the updated text appears.
$ curl http://localhost:8001
Hello, Docker!!!
Press ctrl+c
in the terminal to stop your application.
Summary
In this section, you took a look at setting up your Compose file to add a local database and persist data. You also learned how to use Compose Watch to automatically rebuild and run your container when you update your code.
Related information:
Next steps
In the next section, you'll learn how you can locally test and debug your workloads on Kubernetes before deploying.