Développer votre application Rust
Prérequis
- Vous avez installé la dernière version de Docker Desktop.
- Vous avez suivi les tutoriels du Centre d'apprentissage de Docker Desktop pour vous familiariser avec les concepts de Docker.
- Vous disposez d'un client git. Les exemples de cette section utilisent un client git en ligne de commande, mais vous pouvez utiliser n'importe quel client.
Aperçu
Dans cette section, vous apprendrez à utiliser les volumes et le réseau dans Docker. Vous utiliserez également Docker pour construire vos images et Docker Compose pour rendre tout cela beaucoup plus facile.
Tout d'abord, vous examinerez l'exécution d'une base de données dans un conteneur et comment vous pouvez utiliser les volumes et le réseau pour conserver vos données et permettre à votre application de communiquer avec la base de données. Ensuite, vous rassemblerez tout dans un fichier Compose qui vous permettra de configurer et d'exécuter un environnement de développement local avec une seule commande.
Exécuter une base de données dans un conteneur
Au lieu de télécharger PostgreSQL, de l'installer, de le configurer, puis d'exécuter la base de données PostgreSQL en tant que service, vous pouvez utiliser l'image officielle Docker pour PostgreSQL et l'exécuter dans un conteneur.
Avant d'exécuter PostgreSQL dans un conteneur, créez un volume que Docker peut gérer pour stocker vos données et votre configuration persistantes. Utilisez la fonctionnalité des volumes nommés que Docker fournit au lieu d'utiliser des montages de liaison.
Exécutez la commande suivante pour créer votre volume.
$ docker volume create db-data
Créez maintenant un réseau que votre application et votre base de données utiliseront pour communiquer entre elles. Le réseau est appelé un réseau de pont défini par l'utilisateur et vous offre un service de recherche DNS agréable que vous pouvez utiliser lors de la création de votre chaîne de connexion.
$ docker network create postgresnet
Vous pouvez maintenant exécuter PostgreSQL dans un conteneur et l'attacher au volume et au réseau que vous avez créés précédemment. Docker tire l'image de Hub et l'exécute pour vous localement.
Dans la commande suivante, l'option --mount
sert à démarrer le conteneur avec un volume. Pour plus d'informations, consultez
Volumes Docker.
$ docker run --rm -d --mount \
"type=volume,src=db-data,target=/var/lib/postgresql/data" \
-p 5432:5432 \
--network postgresnet \
--name db \
-e POSTGRES_PASSWORD=mysecretpassword \
-e POSTGRES_DB=example \
postgres
Maintenant, assurez-vous que votre base de données PostgreSQL est en cours d'exécution et que vous pouvez vous y connecter. Connectez-vous à la base de données PostgreSQL en cours d'exécution à l'intérieur du conteneur.
$ docker exec -it db psql -U postgres
Vous devriez voir une sortie comme celle-ci.
psql (15.3 (Debian 15.3-1.pgdg110+1))
Tapez "help" pour obtenir de l'aide.
postgres=#
Dans la commande précédente, vous vous êtes connecté à la base de données PostgreSQL en passant la commande psql
au conteneur db
. Appuyez sur ctrl-d pour quitter le terminal interactif de PostgreSQL.
Obtenir et exécuter l'application d'exemple
Pour l'application d'exemple, vous utiliserez une variante du backend de l'application react-rust-postgres de Awesome Compose.
-
Clonez le dépôt de l'application d'exemple en utilisant la commande suivante.
$ git clone https://github.com/docker/docker-rust-postgres
-
Dans le répertoire du dépôt cloné, exécutez
docker init
pour créer les fichiers Docker nécessaires. Référez-vous à l'exemple suivant pour répondre aux invites dedocker init
.$ docker init Bienvenue dans la 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 ? Rust ? Quelle version de Rust voulez-vous utiliser ? 1.70.0 ? Sur quel port votre serveur écoute-t-il ? 8000
-
Dans le répertoire du dépôt cloné, ouvrez le
Dockerfile
dans un IDE ou un éditeur de texte pour le mettre à jour.docker init
s'est chargé de créer la plupart des instructions dans le Dockerfile, mais vous devrez le mettre à jour pour votre application unique. En plus d'un répertoiresrc
, cette application inclut un répertoiremigrations
pour initialiser la base de données. Ajoutez un montage de liaison pour le répertoiremigrations
à l'étape de construction dans le Dockerfile. Voici le Dockerfile mis à jour.# syntax=docker/dockerfile:1 # Des commentaires sont fournis tout au long de ce fichier pour vous aider à démarrer. # Si vous avez besoin d'aide supplémentaire, consultez le guide de référence du Dockerfile à l'adresse # https://docs.docker.com/reference/dockerfile/ ################################################################################ # Créer une étape pour la construction de l'application. ARG RUST_VERSION=1.70.0 ARG APP_NAME=react-rust-postgres FROM rust:${RUST_VERSION}-slim-bullseye AS build ARG APP_NAME WORKDIR /app # Construire l'application. # Tirez parti d'un montage de cache sur /usr/local/cargo/registry/ # pour les dépendances téléchargées et d'un montage de cache sur /app/target/ pour # les dépendances compilées, ce qui accélérera les constructions ultérieures. # Tirez parti d'un montage de liaison sur le répertoire src pour éviter d'avoir à copier le # code source dans le conteneur. Une fois construit, copiez l'exécutable dans un # répertoire de sortie avant que le /app/target monté en cache ne soit démonté. RUN --mount=type=bind,source=src,target=src \ --mount=type=bind,source=Cargo.toml,target=Cargo.toml \ --mount=type=bind,source=Cargo.lock,target=Cargo.lock \ --mount=type=cache,target=/app/target/ \ --mount=type=cache,target=/usr/local/cargo/registry/ \ --mount=type=bind,source=migrations,target=migrations \ <<EOF set -e cargo build --locked --release cp ./target/release/$APP_NAME /bin/server EOF ################################################################################ # Créer une nouvelle étape pour l'exécution de l'application qui contient le minimum # de dépendances d'exécution pour l'application. Cela utilise souvent une image de base différente # de l'étape de construction où les fichiers nécessaires sont copiés de l'étape de # construction. # # L'exemple ci-dessous utilise l'image debian bullseye comme base pour exécuter l'application. # En spécifiant le tag "bullseye-slim", il utilisera également tout ce qui se trouve être # la version la plus récente de ce tag lorsque vous construirez votre Dockerfile. Si # la reproductibilité est importante, envisagez d'utiliser un digest # (par exemple, debian@sha256:ac707220fbd7b67fc19b112cee8170b41a9e97f703f588b2cdbbcdcecdd8af57). FROM debian:bullseye-slim AS final # Créer un utilisateur non privilégié sous lequel l'application s'exécutera. # Voir https://docs.docker.com/develop/develop-images/dockerfile_best-practices/ #user ARG UID=10001 RUN adduser \ --disabled-password \ --gecos "" \ --home "/nonexistent" \ --shell "/sbin/nologin" \ --no-create-home \ --uid "${UID}" \ appuser USER appuser # Copier l'exécutable de l'étape "build". COPY --from=build /bin/server /bin/ # Exposer le port sur lequel l'application écoute. EXPOSE 8000 # Ce que le conteneur doit exécuter lorsqu'il est démarré. CMD ["/bin/server"]
-
Dans le répertoire du dépôt cloné, exécutez
docker build
pour construire l'image.$ docker build -t rust-backend-image .
-
Exécutez
docker run
avec les options suivantes pour exécuter l'image en tant que conteneur sur le même réseau que la base de données.$ docker run \ --rm -d \ --network postgresnet \ --name docker-develop-rust-container \ -p 3001:8000 \ -e PG_DBNAME=example \ -e PG_HOST=db \ -e PG_USER=postgres \ -e PG_PASSWORD=mysecretpassword \ -e ADDRESS=0.0.0.0:8000 \ -e RUST_LOG=debug \ rust-backend-image
-
Faites un curl sur l'application pour vérifier qu'elle se connecte à la base de données.
$ curl http://localhost:3001/users
Vous devriez obtenir une réponse comme celle-ci.
[{ "id": 1, "login": "root" }]
Utiliser Compose pour développer localement
Lorsque vous exécutez docker init
, en plus d'un Dockerfile
, il crée également un fichier compose.yaml
.
Ce fichier Compose est super pratique car vous n'avez pas à taper tous les paramètres à passer à la commande docker run
. Vous pouvez le faire de manière déclarative en utilisant un fichier Compose.
Dans le répertoire du dépôt cloné, ouvrez le fichier compose.yaml
dans un IDE ou un éditeur de texte. docker init
s'est chargé de créer la plupart des instructions, mais vous devrez le mettre à jour pour votre application unique.
Vous devez mettre à jour les éléments suivants dans le fichier compose.yaml
:
- Décommentez toutes les instructions de la base de données.
- Ajoutez les variables d'environnement sous le service serveur.
Voici le fichier compose.yaml
mis à jour.
# Des commentaires sont fournis tout au long de ce fichier pour vous aider à démarrer.
# Si vous avez besoin d'aide supplémentaire, consultez le guide de référence de Docker compose à l'adresse
# https://docs.docker.com/reference/compose-file/
# 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: .
target: final
ports:
- 8000:8000
environment:
- PG_DBNAME=example
- PG_HOST=db
- PG_USER=postgres
- PG_PASSWORD=mysecretpassword
- ADDRESS=0.0.0.0:8000
- RUST_LOG=debug
# 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
Note that the file doesn't specify a network for those 2 services. When you use Compose, it automatically creates a network and connects the services to it. For more information see Networking in Compose.
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
If you have any other containers running from the previous sections, stop them now.
Now, run the following docker compose up
command to start your application.
$ docker compose up --build
The command passes the --build
flag so Docker will compile your image and then start the containers.
Now test your API endpoint. Open a new terminal then make a request to the server using the curl commands:
$ curl http://localhost:8000/users
You should receive the following response:
[{ "id": 1, "login": "root" }]
Summary
In this section, you took a look at setting up your Compose file to run your Rust application and database with a single command.
Related information:
Next steps
In the next section, you'll take a look at how to set up a CI/CD pipeline using GitHub Actions.