⚠️ Traduction non officielle - Cette documentation est une traduction communautaire non officielle de Docker.

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.

  1. Clonez le dépôt de l'application d'exemple en utilisant la commande suivante.

    $ git clone https://github.com/docker/docker-rust-postgres
    
  2. 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 de docker 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
    
  3. 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épertoire src, cette application inclut un répertoire migrations pour initialiser la base de données. Ajoutez un montage de liaison pour le répertoire migrations à 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"]
  4. Dans le répertoire du dépôt cloné, exécutez docker build pour construire l'image.

    $ docker build -t rust-backend-image .
    
  5. 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
    
  6. 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.