paint-brush
Un guide simplifié pour la « Dockerazition » de Ruby et Rails avec l'application React Front-End par@forison
198 lectures

Un guide simplifié pour la « Dockerazition » de Ruby et Rails avec l'application React Front-End

par Addo Boakye Forison13m2024/08/04
Read on Terminal Reader

Trop long; Pour lire

La dockerisation implique deux concepts clés : les images et les conteneurs. Les images servent de modèles pour les conteneurs, contenant toutes les informations nécessaires pour créer un conteneur. Un conteneur est une instance d'exécution d'une image, comprenant l'image elle-même, un environnement d'exécution et des instructions d'exécution. Dans cet article, nous fournirons un guide pratique pour dockeriser vos applications Rails et React en détail.
featured image - Un guide simplifié pour la « Dockerazition » de Ruby et Rails avec l'application React Front-End
Addo Boakye Forison HackerNoon profile picture
0-item
1-item

Dockeriser votre Ruby on Rails avec une application frontale React peut considérablement améliorer votre flux de travail de développement et votre processus de déploiement. En créant un environnement standardisé pour votre application, vous garantissez un comportement cohérent à travers les différentes étapes de développement, de test, de production et même sur différents systèmes. En fait, il est conçu pour minimiser les problèmes liés aux différences entre les systèmes. Ce guide vous guidera à travers les étapes essentielles pour que votre application Rails et React fonctionne correctement dans les conteneurs Docker.

Docker à la rescousse

Pourquoi Dockeriser une application ?

  • Cohérence entre les environnements :
    • Docker garantit que l'application s'exécute de la même manière quel que soit l'endroit où elle est déployée, que ce soit sur la machine d'un développeur, dans un environnement de test ou sur un serveur de production. Cette cohérence est obtenue en conteneurisant toutes les dépendances et configurations.


  • Gestion des dépendances :
    • Les conteneurs Docker incluent toutes les dépendances nécessaires à l'exécution de l'application. Cela signifie que les variations dans les bibliothèques système ou les dépendances manquantes sur différents systèmes n'affectent pas la fonctionnalité de l'application.


  • Isolement :
    • Les conteneurs Docker s'exécutent indépendamment les uns des autres et du système hôte. Cette isolation évite les conflits entre différentes applications et leurs dépendances sur le même système.


  • Portabilité :
    • Les conteneurs Docker peuvent être facilement déplacés et exécutés sur n'importe quel système prenant en charge Docker, qu'il s'agisse d'une machine locale, d'un service cloud ou d'un serveur dédié. Cela rend l'application hautement portable et flexible en termes de déploiement.


NB : Une connaissance de la syntaxe Docker est requise


La dockerisation implique deux concepts clés : les images et les conteneurs. Les images servent de modèles pour les conteneurs, contenant toutes les informations nécessaires pour créer un conteneur, y compris les dépendances et les configurations de déploiement. Un conteneur est une instance d'exécution d'une image, comprenant l'image elle-même, un environnement d'exécution et des instructions d'exécution. Docker en général établit une norme pour les logiciels d'expédition.


Pour expliquer Docker avec une analogie simple : considérez les conteneurs comme les conteneurs d'expédition dans un chantier, les images comme les articles placés à l'intérieur de ces conteneurs et le navire d'expédition comme le système sur lequel les conteneurs fonctionnent.


Chaque fois que vous configurez et créez votre application, certaines configurations d'environnement sont nécessaires. Par exemple, vous ne pouvez pas exécuter une application Rails sans qu'un environnement Ruby soit installé sur votre système. De même, vous ne pouvez pas exécuter une application React sans Node.js , et vous ne pouvez pas installer de packages React sans un gestionnaire de packages Node comme npm ou Yarn , etc.


Puisque le conteneur fonctionne indépendamment du système de l'utilisateur, nous allons rendre tous ces packages disponibles dans notre conteneur comme nous l'aurions fait si nous l'avions construit directement sur notre système, ainsi, le conteneur agira comme un système sur celui-ci. propre, comme une machine virtuelle. Il existe des différences entre Docker et la machine virtuelle, mais cet exemple sert simplement à expliquer davantage.


Maintenant, allons de l'avant et dockerisons l'application Rails. Pour ce faire, nous aurons besoin de trois fichiers dans notre application Rails : un Dockerfile , un docker-compose.yml et un bin/docker-entrypoint . Examinons chacun de ces fichiers en détail.


NB : Une connaissance de la syntaxe Docker est requise

Fichier Docker

Le Dockerfile est un modèle pour créer un conteneur Docker. Il contient une série d'instructions que Docker utilise pour créer une image, qui peut ensuite être utilisée pour exécuter des conteneurs. Décomposons un Dockerfile pour une application Ruby on Rails et React :

. Image de base

 ARG RUBY_VERSION=3.1.4 FROM ruby:$RUBY_VERSION
  • ARG RUBY_VERSION=3.1.4 : Définit un argument de build nommé RUBY_VERSION avec une valeur par défaut de 3.1.4 . Cela peut être remplacé au moment de la construction.


  • FROM ruby:$RUBY_VERSION : utilise l'image de base ruby avec la version spécifiée par RUBY_VERSION . Cela configure le conteneur avec le runtime Ruby. Tout comme je l'ai mentionné plus tôt, pour exécuter une application Rails, vous devez avoir installé Ruby.

2. Installer les dépendances

 RUN apt-get update -qq && \ apt-get install -y build-essential libvips bash bash-completion libffi-dev tzdata postgresql curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man
  • apt-get update -qq : Met à jour la liste des packages à partir des référentiels, avec -qq pour une sortie silencieuse.


  • apt-get install -y ... : Installe divers packages :
    • build-essential : packages essentiels pour la création de logiciels (comme GCC).

    • libvips : Bibliothèque de traitement d'images.

    • bash , bash-completion : Shell Bash et son auto-complétion.

    • libffi-dev : bibliothèque d'interface de fonctions étrangères.

    • tzdata : Données de fuseau horaire.

    • postgresql : client de base de données PostgreSQL.

    • curl : Outil pour transférer des données depuis des URL.


  • apt-get clean : nettoie le référentiel local des fichiers de package récupérés.


  • rm -rf /var/lib/apt/lists/ /usr/share/doc /usr/share/man : Supprime les listes de packages et la documentation pour réduire la taille de l'image.

3. Installez Node.js et Yarn

 RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && \ apt-get install -y nodejs && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && \ apt-get install -y yarn
  • curl -fsSL https://deb.nodesource.com/setup_current.x | bash - : télécharge et exécute le script d'installation de NodeSource pour installer Node.js.


  • apt-get install -y nodejs : Installe Node.js.


  • curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - : Ajoute la clé Yarn GPG pour vérifier ses packages.


  • echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list : Ajoute le référentiel de Yarn à la liste des sources.


  • apt-get update && apt-get install -y yarn : met à jour la liste des packages et installe Yarn.

4. Variables d'environnement

 ENV NODE_OPTIONS=--openssl-legacy-provider
  • ENV NODE_OPTIONS=--openssl-legacy-provider : définit une variable d'environnement pour activer la prise en charge OpenSSL héritée pour Node.js.

5. Définir le répertoire de travail

 WORKDIR /rails
  • WORKDIR /rails : Définit le répertoire de travail pour les instructions ultérieures sur /rails .

6. Construire des arguments et des variables d'environnement

 ARG RAILS_ENV ENV RAILS_ENV=$RAILS_ENV
  • ARG RAILS_ENV : définit un argument de construction nommé RAILS_ENV pour spécifier l'environnement Rails (comme development , test , production ).


  • ENV RAILS_ENV=$RAILS_ENV : Définit la variable d'environnement RAILS_ENV à la valeur de l'argument de construction.

7. Installer les gemmes d'application

 COPY Gemfile Gemfile.lock ./ RUN bundle install
  • COPY Gemfile Gemfile.lock ./ : Copie le Gemfile et Gemfile.lock dans le répertoire de travail.


  • RUN bundle install : installe les gemmes Ruby spécifiées dans le Gemfile .

8. Installer les dépendances frontales

 COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile
  • COPY package.json yarn.lock ./ : Copie le package.json et yarn.lock dans le répertoire de travail.


  • RUN yarn install --frozen-lockfile : installe les dépendances frontales à l'aide de Yarn, en s'assurant qu'il utilise les versions exactes dans yarn.lock .

9. Copier le code de candidature

 COPY . .
  • COPY . . : Copie tout le code de l'application dans le répertoire de travail.

10. Précompiler le code Bootsnap

 RUN bundle exec bootsnap precompile --gemfile app/ lib/
  • RUN bundle exec bootsnap precompile --gemfile app/ lib/ : précompile le cache Bootsnap pour des temps de démarrage plus rapides de l'application Rails. Bootsnap est un joyau qui accélère les temps de démarrage de Ruby et Rails en mettant en cache des calculs coûteux.

11. Précompiler les actifs pour la production

 RUN if [ "$RAILS_ENV" = "production" ]; then \ SECRET_KEY_BASE=1 bin/rails assets:precompile; \ fi
  • RUN if [ "$RAILS_ENV" = "production" ]; then ... : exécute sous condition la pré-compilation des actifs uniquement si RAILS_ENV est défini sur production . Cette étape est cruciale pour préparer les actifs à un environnement de production.

12. Script de point d'entrée

 COPY bin/docker-entrypoint /rails/bin/ RUN chmod +x /rails/bin/docker-entrypoint
  • COPY bin/docker-entrypoint /rails/bin/ : copie un script de point d'entrée personnalisé dans le conteneur.


  • RUN chmod +x /rails/bin/docker-entrypoint : Rend le script du point d'entrée exécutable.

13. Définir le point d'entrée et la commande

 ENTRYPOINT ["/rails/bin/docker-entrypoint"] EXPOSE 5000 // you can use any port of your choice CMD ["./bin/rails", "server"]
  • ENTRYPOINT ["/rails/bin/docker-entrypoint"] : Définit le script de point d'entrée qui s'exécutera au démarrage du conteneur. Ce script configure généralement l'environnement, prépare la base de données et démarre l'application.


  • EXPOSE 5000 : Indique que le conteneur écoute sur le port 5000. Il s'agit d'une fonctionnalité de documentation et ne publie pas le port.


  • CMD ["./bin/rails", "server"] : Spécifie la commande par défaut à exécuter au démarrage du conteneur, qui consiste à démarrer le serveur Rails.

docker-compose.yml

Le fichier docker-compose.yml est utilisé pour définir et exécuter des applications Docker multi-conteneurs. Il vous permet de configurer les services, réseaux et volumes de votre application dans un seul fichier. Dans ce cas, nous allons utiliser deux services. Voici le fichier docker-compose.yml pour l'application Rails :

1. Service de base de données ( db )

 codedb: image: postgres:14.2-alpine container_name: demo-postgres-14.2 volumes: - postgres_data:/var/lib/postgresql/data command: "postgres -c 'max_connections=500'" environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - "5432:5432"
  • image: postgres:14.2-alpine : Spécifie l'image Docker à utiliser pour ce service. Dans ce cas, il s'agit de l'image PostgreSQL 14.2 basée sur la distribution Alpine Linux. Les images alpines sont connues pour leur petite taille, ce qui peut contribuer à réduire la taille globale de l’image.


  • container_name: demo-postgres-14.2 : Nomme le conteneur demo-postgres-14.2 . Ce nom est utilisé pour référencer le conteneur dans les commandes et les journaux.


  • volumes :
    • postgres_data:/var/lib/postgresql/data: monte un volume nommé postgres_data sur /var/lib/postgresql/data à l'intérieur du conteneur. Ce répertoire est l'endroit où PostgreSQL stocke ses données, garantissant que les données de la base de données persistent entre les redémarrages du conteneur.


  • command: "postgres -c 'max_connections=500'" : Remplace la commande par défaut de l'image PostgreSQL. Il démarre PostgreSQL avec une option de configuration permettant d'augmenter le nombre maximum de connexions à 500.


  • environment :
    • POSTGRES_DB: ${POSTGRES_DB} : Définit le nom de la base de données par défaut à créer, à l'aide d'une variable d'environnement POSTGRES_DB .

    • POSTGRES_USER: ${POSTGRES_USER} : définit le nom d'utilisateur par défaut pour accéder à la base de données PostgreSQL, à l'aide de la variable d'environnement POSTGRES_USER .

    • POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} : Définit le mot de passe de l'utilisateur par défaut, en utilisant la variable d'environnement POSTGRES_PASSWORD .


  • ports :
    • "5432:5432" : mappe le port 5432 sur l'hôte au port 5432 dans le conteneur. Cela permet d'accéder à PostgreSQL sur la machine hôte via le port 5432.

2. Service d'application Web ( demo-web )

 codedemo-web: build: context: . args: - RAILS_ENV=${RAILS_ENV} command: "./bin/rails server -b 0.0.0.0" environment: - RAILS_ENV=${RAILS_ENV} - POSTGRES_HOST=${POSTGRES_HOST} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - RAILS_MASTER_KEY=${RAILS_MASTER_KEY} volumes: - .:/rails - app-storage:/rails/storage depends_on: - db ports: - "3000:3000"
  • build:

    • context: . : Spécifie le contexte de construction de l'image Docker. Dans ce cas, . fait référence au répertoire courant. Cela signifie que Docker utilisera le Dockerfile dans le répertoire actuel pour créer l'image.
    • args :
      • RAILS_ENV=${RAILS_ENV} : transmet l'argument de construction RAILS_ENV au processus de construction Docker, vous permettant de spécifier l'environnement Rails (comme development , test ou production ).


  • command: "./bin/rails server -b 0.0.0.0" : remplace la commande par défaut de l'image Docker. Démarre le serveur Rails et le lie à toutes les interfaces réseau ( 0.0.0.0 ), ce qui est nécessaire pour que le service soit accessible depuis l'extérieur du conteneur.


  • environment:

    • RAILS_ENV=${RAILS_ENV} : Définit l'environnement Rails à l'intérieur du conteneur à l'aide de la variable d'environnement RAILS_ENV .

    • POSTGRES_HOST=${POSTGRES_HOST} : Définit l'adresse de l'hôte PostgreSQL.

    • POSTGRES_DB=${POSTGRES_DB} : Définit le nom de la base de données.

    • POSTGRES_USER=${POSTGRES_USER} : Définit l'utilisateur PostgreSQL.

    • POSTGRES_PASSWORD=${POSTGRES_PASSWORD} : Définit le mot de passe de l'utilisateur PostgreSQL.

    • RAILS_MASTER_KEY=${RAILS_MASTER_KEY} : Définit la clé principale Rails, qui est utilisée pour crypter les informations d'identification et autres secrets.


  • volumes :

    • .:/rails : monte le répertoire actuel (où se trouve le fichier docker-compose.yml ) sur /rails à l'intérieur du conteneur. Cela vous permet de modifier des fichiers sur votre hôte et de refléter ces modifications dans le conteneur.

    • app-storage:/rails/storage : monte un volume nommé app-storage sur /rails/storage à l'intérieur du conteneur. Ceci est généralement utilisé pour stocker des fichiers spécifiques à Rails tels que les journaux, les téléchargements et les fichiers mis en cache.


  • depends_on :

    • db : garantit que le service demo-web attend que le service db soit prêt avant de démarrer. Docker Compose gère l'ordre de démarrage des services en fonction de ce paramètre.
  • ports:

    • "3000:3000" : Mappe le port 3000 sur l'hôte au port 3000 dans le conteneur. Cela vous permet d'accéder à l'application Rails sur la machine hôte via le port 3000.

    Volumes

     codevolumes: postgres_data: app-storage:
    • postgres_data : définit un volume nommé postgres_data utilisé par le service db pour conserver les données PostgreSQL.
    • app-storage : définit un volume nommé app-storage utilisé par le service demo-web pour conserver les données spécifiques à l'application, telles que les téléchargements et les journaux.

bin/docker-point d'entrée

Le script bin/docker-entrypoint est une partie cruciale de la configuration de Docker. Il est exécuté au démarrage du conteneur et gère généralement la configuration de l'environnement, la préparation de la base de données et d'autres tâches d'initialisation nécessaires avant de démarrer l'application principale. Voici un exemple de script bin/docker-entrypoint et une explication détaillée de chaque partie :

Shebang et sortie en cas d'erreur

 bashCopy code#!/bin/bash set -e
  • #!/bin/bash : Cette ligne spécifie que le script doit être exécuté à l'aide du shell Bash.


  • set -e : Cela demande au script de se terminer immédiatement si une commande renvoie un code de sortie différent de zéro. Cela permet de garantir qu'en cas d'échec d'une étape, le script arrête l'exécution, ce qui peut empêcher les étapes suivantes de s'exécuter dans un état non valide.


Création ou migration conditionnelle de bases de données

 # If running the rails server then create or migrate existing database if [ "${*}" == "./bin/rails server" ]; then ./bin/rails db:create ./bin/rails db:prepare fi


  • if [ "${*}" == "serveur ./bin/rails" ]; then ... fi : Cette instruction conditionnelle vérifie si la commande passée au script ( "${*}" ) est ./bin/rails server . Le * est un paramètre spécial qui contient tous les paramètres de position transmis au script.


  • ./bin/rails base de données

    : Si la condition est remplie, cette commande tentera de créer la base de données. Cela équivaut à exécuter rails db:create qui configure la base de données comme défini dans le fichier de configuration de la base de données ( config/database.yml ).


  • ./bin/rails base de données

    : Cette commande exécutera rails db:prepare , ce qui garantit que la base de données est configurée et migrée. Il créera la base de données si elle n'existe pas et exécutera des migrations si la base de données est déjà créée. Il s'agit d'une combinaison de rails db:create et rails db:migrate .

    Exécution du processus principal

     bashCopy codeexec "${@}"
    • exec "${@}" : Ceci remplace le processus shell actuel par la commande passée en arguments au script. Le symbole @ contient tous les paramètres de position transmis au script. Par exemple, si le script est appelé avec ./bin/rails server , cette ligne exécute effectivement ./bin/rails server en tant que processus principal du conteneur.

Conclusion

Un Dockerfile bien conçu est essentiel pour créer un environnement fiable et cohérent pour votre application Ruby on Rails et React. En définissant l'image de base, en définissant les variables d'environnement et en installant les dépendances, vous vous assurez que votre application fonctionne correctement dans différents environnements.


Docker rationalise non seulement votre processus de développement, mais améliore également la fiabilité de votre application en production. Il existe des domaines d'optimisation, mais ceci n'est qu'un aperçu général de la façon de dockeriser l'application Rails.

Script complet pour le Dockerfile résultant, docker-compose.yml et bin/docker-entrypoint

 ARG RUBY_VERSION=3.1.4 FROM ruby:$RUBY_VERSION # Install dependencies RUN apt-get update -qq && \ apt-get install -y build-essential libvips bash bash-completion libffi-dev tzdata postgresql curl && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /usr/share/doc /usr/share/man # Install Node.js and Yarn RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - && \ apt-get install -y nodejs && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && \ apt-get install -y yarn # Set environment variable to enable legacy OpenSSL support ENV NODE_OPTIONS=--openssl-legacy-provider # Rails app lives here WORKDIR /rails # Set environment variable for the build ARG RAILS_ENV ENV RAILS_ENV=$RAILS_ENV # Install application gems COPY Gemfile Gemfile.lock ./ RUN bundle install # Install frontend dependencies COPY package.json yarn.lock ./ RUN yarn install --frozen-lockfile # Copy application code COPY . . # Precompile bootsnap code for faster boot times RUN bundle exec bootsnap precompile --gemfile app/ lib/ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY RUN if [ "$RAILS_ENV" = "production" ]; then \ SECRET_KEY_BASE=1 bin/rails assets:precompile; \ fi # Entrypoint prepares the database. COPY bin/docker-entrypoint /rails/bin/ RUN chmod +x /rails/bin/docker-entrypoint # Use an absolute path for the entry point script ENTRYPOINT ["/rails/bin/docker-entrypoint"] # Start the server by default, this can be overwritten at runtime EXPOSE 5000 CMD ["./bin/rails", "server"]


 services: db: image: postgres:14.2-alpine container_name: demo-postgres-14.2 volumes: - postgres_data:/var/lib/postgresql/data command: "postgres -c 'max_connections=500'" environment: POSTGRES_DB: ${POSTGRES_DB} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} ports: - "5432:5432" demo-web: build: context: . args: - RAILS_ENV=${RAILS_ENV} command: "./bin/rails server -b 0.0.0.0" environment: - RAILS_ENV=${RAILS_ENV} - POSTGRES_HOST=${POSTGRES_HOST} - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - RAILS_MASTER_KEY=${RAILS_MASTER_KEY} volumes: - .:/rails - app-storage:/rails/storage depends_on: - db ports: - "3000:3000" volumes: postgres_data: app-storage:



 #!/bin/bash set -e # If running the rails server then create or migrate existing database if [ "${*}" == "./bin/rails server" ]; then ./bin/rails db:create ./bin/rails db:prepare fi exec "${@}"