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 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.
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.
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.
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
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 :
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. 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. 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. 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. WORKDIR /rails
WORKDIR /rails
: Définit le répertoire de travail pour les instructions ultérieures sur /rails
. 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. 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
. 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
. COPY . .
COPY . .
: Copie tout le code de l'application dans le répertoire de travail. 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. 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. 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. 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. 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 :
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.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. 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. 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 :
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
"${*}"
) 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
.
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. 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.
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 "${@}"