Julien Philippon

Optimiser docker pour le développement

Gagner du temps sur le lancement d’un projet est un point assez simple à mettre en place pour améliorer la productivité. Cet article concerne quelques pistes liées à l’utilisation de docker en développement et est un peu la suite de Automatiser l’installation d’un projet.

1) Utilisez des images distantes si possible

Si vous n’avez pas de paquet ou de manipulation spécifique à faire dans votre projet, essayez d’utiliser directement des images officielles. Vous pouvez jouer avec le paramètre command pour lancer le projet :

services:
  www:
    image: node:14
    command: sh -c "cd /app && npm run dev"
    working_dir: /app
    volumes:
      - './www:/app'

2) Créez vos propres images

Si vous n’avez pas trouvé d’image correspondante sur docker hub, pourquoi ne pas créer une image de build qui comporte tout ce qui est nécessaire séparément et utiliser ensuite l’image buildée sur tous vos projets.

services:
  www:
    image: mon.registry.com/username/monimage:latest
    volumes:
      - './www:/app'

Ceci est un grand avantage lorsque vous avez plusieurs projets : Docker téléchargera l’image qu’une seule fois et utilisera la même à chaque docker-compose up.

3) Faites deux fichiers Dockerfile pour séparer les environnements

Ceci dans le cas ou des choses sont à installer dans l’image pour faire fonctionner le projet. Deux fichiers docker-compose.yml seront aussi nécessaires, afin de différencier le process entre la prod/préprod et le développement.

Pourquoi ? Comme vous utilisez forcément un volume pour travailler sur votre projet, celui-ci écrase ce qui a été copié dans l’image du build.

D’une part, supprimer le COPY sur celui de dev : il peut être très long selon votre projet, le fait de le retirer accélèrera la phase de build.

Retirez les RUN npm install ou autres installateurs de paquets dans ce genre, car de la même façon les nodes_modules seront installés dans l’image du container et seront écrasés par la suite lors du montage du volume. Préférez installer ces packages à l’aide d’un script.

Au contraire, dans le Dockerfile pour la production, vous n’aurez pas de volume sur les fichiers du projet, intégrez donc le COPY et les RUN d’installations des paquets.

Par exemple, voici deux Dockerfile d’un projet ou le paquet wkhtmltopdf est nécessaire pour générer des pdf :

# Dockerfile.dev (Utilisé pour le developpement)
FROM node:14
RUN apt-get update && \
    apt-get install -y \
      wkhtmltopdf \
    && rm -rf /var/lib/apt/lists/*
WORKDIR /app
CMD npm run dev
# Dockerfile (Utilisé pour les autres environnements)
FROM node:14
RUN apt-get update && \
    apt-get install -y \
      wkhtmltopdf \
    && rm -rf /var/lib/apt/lists/*
COPY . /app
WORKDIR /app
RUN npm install
CMD npm run start

On pourrait même pousser le bouchon encore plus loin en créant une image parente séparée du build du projet, comportant l’installation de wkhtmltopdf (mélange des points 1, 2 et 3) :

# Dockerfile (build dans un projet séparé, pushé sur monregistry/node-with-wkhtmltopdf)
FROM node:14
RUN apt-get update && \
    apt-get install -y \
      wkhtmltopdf \
    && rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Dockerfile (Utilisé pour la production)
FROM monregistry/node-with-wkhtmltopdf
COPY . /app
RUN npm install
CMD npm run start
# Pas besoin de Dockerfile pour le développement, tout peut se faire dans
# le docker-compose.yml
services:
  api:
    image: monregistry/node-with-wkhtmltopdf
    command: sh -c "npm run dev"
    volumes:
      - './www:/app'

J’espère que cela vous donnera quelques pistes pour optimiser le lancement de vos projets 😄.