Rails & Docker
Publié il y a presque 3 ans~3 min
Etre développeu(se)r, c'est bien souvent travailler en équipe :juggling::juggling::juggling:. Mais qui n'a jamais connu LA fameuse installation qui prend une journée (ou plus...) à cause d'un souci d'environnement ou de dépendances ? Heureusement, Docker est là ! Graĉe à sa logique de conteneurs, il permet en effet d'encapsuler des applicatifs avec leurs dépendances, nous délivrant ainsi des soucis de portabilité d'un projet.
Sur la base d'un projet Ruby On Rails classique, nous allons mettre en place les différents éléments nécessaires à la dockerisation de celui-ci.
Pré-requis
- Docker et Docker Compose
- Un projet Ruby On Rails (≥ 5.1) utilisant Webpacker et PostgreSQL (≥ 10)
Un projet de démonstration a été créé dans le cadre de cet article, n'hésitez donc pas à vous y référer pour plus de détails (scripts, ...) !
Dockerfile
Tout projet Docker est défini par une image d'origine, qui servira ensuite de base pour la construction des différents conteneurs (application, base de données, ...). Pour ce faire, il suffit de créer un fichier sobrement nommé Dockerfile
à la racine de notre projet :
1FROM ruby:2.5.5-alpine23ARG PRECOMPILEASSETS4ARG RAILS_ENV56ENV SECRET_KEY_BASE foo7ENV RAILS_ENV ${RAILS_ENV}8ENV RAILS_SERVE_STATIC_FILES true910RUN apk add --update --no-cache \11 build-base \12 git \13 postgresql-dev \14 postgresql-client \15 imagemagick \16 nodejs-current \17 yarn \18 python2 \19 tzdata \20 file2122RUN gem install bundler23# Install gems24RUN mkdir /gems25WORKDIR /gems26COPY Gemfile .27COPY Gemfile.lock .28RUN bundle install -j4 --retry 3 \29 # Remove unneeded files (cached *.gem, *.o, *.c)30 && rm -rf /usr/local/bundle/cache/*.gem \31 && find /usr/local/bundle/gems/ -name "*.c" -delete \32 && find /usr/local/bundle/gems/ -name "*.o" -delete3334ARG INSTALL_PATH=/railsondocker35ENV INSTALL_PATH $INSTALL_PATH3637WORKDIR $INSTALL_PATH38COPY . .3940# Precompile assets (or not)41RUN docker/potential_asset_precompile.sh $PRECOMPILEASSETS4243CMD ["docker/startup.sh"]
Le point de départ de notre fichier est une image Docker pour Ruby. On utilise ici une version dite "alpine", c'est-à-dire embarquant le minimum requis pour optimiser le poids de l'image finale générée.
Nous installons ensuite les différentes librairies nécessaires (postgresql, nodejs, ...) et les gems déclarées dans le Gemfile
(avec un peu de nettoyage en fin de tâche, là encore pour optimiser le poids final).
Pour finir nous précompilons les assets (si besoin) avant de lancer la commande globale déclarée via l'instruction CMD
, qui se chargera de lancer le serveur (Puma) après avoir préparé la base de données (cf. script startup.sh
).
A noter l'utilisation de variables qui nous permettrons de construire une image spécifique selon l'environnement (développement, production, ...). Ces variables seront définies dans chaque fichier docker-compose.yml
.
Docker Compose
Notre constructeur général étant maintenant prêt, ne reste plus qu'à définir les différents conteneurs de notre application, avec les variations éventuelles en fonction de l'environnement.
En mode développement, Rails et Webpacker sont séparés, afin d'améliorer la réactivité de l'ensemble. Le fichier docker-compose.yml
est assez simple à comprendre, sa syntaxe restant assez claire :
1version: '3.0'2services:3 db:4 image: postgres:11-alpine5 ports:6 - 5433:54327 environment:8 POSTGRES_PASSWORD: postgres910 webpacker:11 image: railsondocker_development12 command: ["./docker/start_webpack_dev.sh"]13 environment:14 - NODE_ENV=development15 - RAILS_ENV=development16 - WEBPACKER_DEV_SERVER_HOST=0.0.0.017 volumes:18 - .:/railsondocker:cached19 ports:20 - 3035:30352122 app:23 image: railsondocker_development24 build:25 context: .26 args:27 - PRECOMPILEASSETS=NO28 environment:29 - RAILS_ENV=development30 links:31 - db32 - webpacker33 ports:34 - 3000:300035 volumes:36 - .:/railsondocker:cached
Nos trois conteneurs sont donc liés à des images (issues du Dockerfile
, à l’exception de PostgreSQL, pour lequel nous faisons appel à une image "alpine"). On leur assigne des ports, et éventuellement des commandes à exécuter au lancement.
Dans certains cas on définira des arguments ou variables d’environnements, utiles pour le Dockerfile
.
Enfin les liens entre services sont déclarés dans le conteneur app
, dans la partie links
.
Configuration de Rails
Maintenant que la partie Docker est mise en place, il faut effectuer quelques ajustements dans la configuration de notre projet Ruby On Rails, en particulier pour tenir compte des variables définies dans les fichiers Compose :
config/database.yml
, pour lehost
et lesusername
/password
config/webpacker.yml
, pour lehost
du serveur de Webpackerconfig/environments/*.rb
, pour reporter les variables définies dans ledocker-compose.yml
(optionnel)
🎉
Et voilà ! Il ne reste maintenant plus qu’à lancer la commande docker-compose build
pour construire notre image Docker, puis la commande docker-compose up
pour lancer notre projet sur localhost:3000
! Par la suite, on pourra ajouter de nouveaux conteneurs (ou services) : serveur mail, ... 🙂