Quoi
À la recherche d’un CRM pour un petit boulot, je découvre Creme CRM. Selon mon product owner, il y a toutes les fonctionnalités souhaitées. Top!
Ma prod est à base de conteneurs ; il faut « dockeriser » l’outil. Creme est une application Python-Django. Cela ne devrait pas poser de problème particulier, python étant très bien supporté dans Docker.
Comment
Le site officiel renvoi vers le repo git et le README explique la marche à suivre pour lancer l’application.
Il s’avère que Django a une particularité. Il optimise les fichiers statiques (JS, CSS, HTML, images?) avec un outil écrit en java. Il faut java pour faire tourner une application Django avec de bonne performances.
Il s’avère que Django a une deuxième particularité. Il dépend de Pillow, une bibliothèque logicielle de manipulation d’images. Et Pillow doit se compiler sur la machine lors de son installation. Je n’ai pas l’impression que ce soit utilisé par Creme mais dans le doute et pour avoir un packaging Django un peu généraliste, je vais la garder. Il faut un compilateur C et quelques bibliothèques logicielles de développement.
Pour ne pas garder cet embonpoint dans mon image docker finale, je vais faire une construction en deux phases. La première phase fera la génération des médias et la compilation des dépendances, la seconde fera l’image finale, sans java ni compilateur.
Je vais aussi utiliser un « virtual env ». Ce n’est habituellement pas conseillé pour une image docker car le conteneur fait déjà l’isolation de l’environnent applicatif vis-à-vis de l’hôte. Mais dans mon cas, c’est plus pratiques pour transporter les dépendances Python d’une phase à l’autre sans devoir fouiller dans les répertoires système.
Cela donne :
FROM python:3.7-alpine AS django-builder-alpine
RUN apk add --no-cache openjdk11-jre
RUN apk add --no-cache jpeg-dev zlib-dev
RUN apk add --no-cache build-base linux-headers
WORKDIR /app
ENV VIRTUAL_ENV=/app/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
COPY creme/requirements.txt .
RUN pip install -r requirements.txt
COPY . .
# set sqlite backend, else it requires mysql client to be installed
RUN echo "DATABASES={'default':{'ENGINE':'django.db.backends.sqlite3'}}" > creme/local_settings.py
RUN python manage.py generatemedia
FROM python:3.7-alpine
RUN apk add --no-cache redis jpeg zlib
WORKDIR /app
ENV VIRTUAL_ENV=/app/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
COPY --from=django-builder-alpine /app .
# needed for ingress auto discovery
EXPOSE 8000
CMD redis-server & \
python manage.py migrate && \
python manage.py creme_populate && \
python manage.py creme_job_manager & \
python manage.py runserver 0:8000
Limitations
- l’image propose le serveur django de développement ; il est certainement moins optimisé qu’un apache+mod_python ou un gunicorn
- l’image propose le moteur de base de données SQLite ; il n’est pas conseillé pour une utilisation avec plusieurs utilisateurs simultanés. Cela pourrait se changer par simple configuration (fichier
local_settings
) - l’image embarque tous les composants – webapp, db, ordonnanceur, cache – dans le même conteneur ; un déploiement plus élaboré les aurait séparés
Dans la pratique, pour notre petit usage, cela fonctionne parfaitement.
Résultat
L’image de construction pèse 584MB, l’image finale 176MB, une économie de 412MB, environ 70%. La même tentative avec une base Debian-slim donne une image de construction de 508MB et une image finale de 289MB.
EOF
# Deux précisions
Posté par Quentin Pradet . Évalué à 9.
Merci pour ton retour d'expérience !
Ce n'est pas Django qui fait ça, mais https://pypi.org/project/django-mediagenerator/, une app Django qui a décidé de faire appel à YUI. Et creme utilise cette application. (Qui n'est d'ailleurs pas mise à jour depuis 2015.)
C'est une dépendance optionnelle, en effet. Sous Linux, tu n'as besoin de la compiler que si tu utilises musl (c'est ton cas avec Alpine), sinon avec la glibc les wheels manylinux fournies par le projet Pillow s'installent sans compilation.
# Java ??
Posté par matteli . Évalué à 2.
J'utilise Django depuis quelques années et je n'avais jamais entendu parler d'un bout de code en java. Rien non plus sur le site officiel.
Tu aurais un lien qui explique ça ?
[^] # Re: Java ??
Posté par matteli . Évalué à 4.
Bon le temps d'écrire ça et j'ai la réponse au-dessus.
# Quelques précisions
Posté par GuieA_7 (site web personnel) . Évalué à 10.
[je suis le développeur principal de CremeCRM]
Bonsoir,
Cette dépendance n'est pas intrinsèque à Django, mais à CremeCRM. Pour info, nous utilisions une app externe 'mediagenerator' bien avant que Django ait sa gestion actuelle des assets, mais comme sont développement a été stoppée (elle n'est plus compatible depuis longtemps avec les versions récentes de Django) j'ai intégré cette app à notre code, j'ai enlevé la plupart des trucs inutiles pour nous, et porté vers les versions récentes de Django puis Python 3.
Il est tout à fait possible de se passer de Java avec la bonne configuration, mais le JS et le CSS ne sont alors plus minifiés.
Et oui les images subissent un traitement: les assets finaux sont renommés et contiennent un hash dans leur nom (le nom change donc si ont modifie l'image), ce qui permet de dire au navigateur de garder les images en cache aussi longtemps que possible.
Quand j'aurai le temps (spoileur: pas une priorité du tout) je regarderai si les minifieurs JS/CSS écrits en Python donnent de bons résultats histoire de pouvoir enlever Java des dépendances de base.
Il s'agit là encore d'une dépendance de Creme, pas de Django. On s'en sert de manière très légère certes, mais si on s'en sert (cherche des
from PIL
).J'espère que CremeCRM vous satisfera (même si effectivement on ne conseille pas spécialement SQLite pour autre chose que le développement, voire une utilisation locale mono-utilisateur).
# Sans vouloir être méchant
Posté par Pol' uX (site web personnel) . Évalué à 6.
=> Poubelle. Car comme le dit la sage documentation :
https://docs.djangoproject.com/fr/3.0/intro/tutorial01/#the-development-server
Adhérer à l'April, ça vous tente ?
[^] # Re: Sans vouloir être méchant
Posté par Crazy Diver . Évalué à 4.
Sans vouloir être méchant 2 :
- Plusieurs services dans le même container,
- aucun chemins absolu,
- et le tout tourne en root
Et pour la route, j’étais tombé sur cet article qui explique pourquoi il vaut mieux éviter alpine pour du python :
https://pythonspeed.com/articles/alpine-docker-python/
[^] # Re: Sans vouloir être méchant
Posté par steph1978 . Évalué à 4.
Ce n'est pas une très bonne pratique mais ce n'est pas rédhibitoire non plus.
pas compris
Cela se configure au déploiement, par exemple avec un
docker run -u 1001
Il dit:
Pour avoir testé slim et alpine, il n'y a pas de différence perceptible de temps de build.
C'est ce que je constate pour la première phase. Mais une fois la deuxième phase effectuée, l'image résultante est plus petite: -113MB.
Trop tard :)
Je verrai à l'usage. Je backup/restore tous les jours actuellement au cas où.
[^] # Re: Sans vouloir être méchant
Posté par claudex . Évalué à 7. Dernière modification le 19 avril 2020 à 09:40.
(merci pour le journal, c'est sympa d'avoir du contenu technique)
Ça rend le scaling plus compliqué (mais peut-être que ce n'est pas un problème ici, surtout avec le sqlite). Et ça rend le monitoring plus compliqué. Si ton process redis meurt, tu ne vas pas le voir tout de suite.
« Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche
[^] # Re: Sans vouloir être méchant
Posté par LeBouquetin (site web personnel, Mastodon) . Évalué à 7. Dernière modification le 19 avril 2020 à 00:47.
Nombre de logiciels sont "dockerises" de cette manière.
Quel est le problème (outre que ce n'est pas dans la philosophie docker) ?
#tracim pour la collaboration d'équipe __ #galae pour la messagerie email __ dirigeant @ algoo
[^] # Re: Sans vouloir être méchant
Posté par steph1978 . Évalué à 3.
J'ai un reverse proxy HTTPS devant ce qui devrait me garantir un minimum de sécurité.
J'imagine que si ils ne le recommandent pas, c'est parce qu'il gère sûrement pas très bien les connections simultanées. Ça tombe bien, la base de données que j'ai choisi pour ce petit déploiement n'est pas vraiment faîte pour ça non plus.
[^] # Re: Sans vouloir être méchant
Posté par Astaoth . Évalué à 4.
Et il protège contre les fuzzers web ?
Emacs le fait depuis 30 ans.
[^] # Re: Sans vouloir être méchant
Posté par steph1978 . Évalué à 2.
Pas spécialement pourquoi ? tu conseilles quelque chose ?
[^] # Re: Sans vouloir être méchant
Posté par Astaoth . Évalué à 5.
Ca me fait toujours tiquer quand je vois un projet disant "oui on a mis en prod l'env de dev qui est pas très sécurisé et carrément déconseillé pour la prod par tout le monde, mais tkt on gère et en plus on a mis un reverse-proxy/firewall/whatever". Ca me fait par contre pas tiquer quand je tombe, quelques temps plus tard, sur une news annoncant un leak massif de données de la plateforme en question, ou que je recois des spams venant de là.
Penser "sécurité" pendant les process de dev, mais aussi de mise en prod, ce sont des efforts certes, mais qui permettent de grandement réduire la surface d'attaque sur une webapp.
Pas mettre en prod un env de dev déjà. Si vous avez une DSI qui fait aussi de la sécurité, aller leur demander des conseils, c'est leur métier. Si vous avez un WAF, faire passer les flux accédant à l'appli par là (le WAF servant aussi de reverse-proxy). Si vous en avez pas, bah faudrait penser à en mettre un, au moins pour limiter les XSS et les SQLi. Comme t'as déjà un reverse proxy, tu peux en mettre un dessus : si c'est un nginx tu as naxsi ; si c'est un apache, tu as modsecurity. Et garder un oeil sur les logs aussi, y a toujours pleins de choses intéressantes dedans.
Emacs le fait depuis 30 ans.
# Docker + Django + Apache
Posté par Jérôme Flesch (site web personnel) . Évalué à 4. Dernière modification le 18 avril 2020 à 23:26.
J'ai récemment passé le site openpaper.work dans Docker. C'est aussi du Django. J'avais vu beaucoup de doc et tutoriels de dockerisation qui montraient comment le faire en utilisant aussi le serveur web de développement de Django. Bien que ça peut peut-être faire l'affaire dans un environnement cloud, ça ressemble quand même à une mauvaise idée. Dans mon cas, je n'ai de toute façon qu'un seul conteneur qui tourne. Donc j'ai choisi de continuer à utiliser un serveur Apache dans le conteneur. Ça donne ça: Dockerfile + start.sh + docker.
Comme c'est la 1ère fois que je dockerise quelque-chose de sérieux, je serais intéressé d'avoir l'avis de gens qui s'y connaissent mieux en Docker.
[^] # Re: Docker + Django + Apache
Posté par palm123 (site web personnel) . Évalué à 5.
grouper les RUN, comme indiqué dans les bonnes pratiques Docker, pour réduire le nombre de couches (layers)
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
suivre les préceptes de
https://www.dajobe.org/blog/2015/04/18/making-debian-docker-images-smaller/
et surtout, lire les 3 articles de Jérôme Petazzoni
https://enix.io/fr/blog/cherie-j-ai-retreci-docker-part1/
ウィズコロナ
# état de l'art
Posté par Alex G. . Évalué à 2.
Hello,
Plusieurs choses qui ne sont pas "état de l'art" dans ton DockerFile (après lecture en diagonale)
USER: ton container run en
root
, c'est mal pour la sécurité ! Il faut créer un user, lui donner les droits sur les bons dossiersVOLUMES: tout ce qui est data / qui bouge doit être dans un volume, et tu peux le déclarer dans ton DockerFile. Si ton volume doit avoir déjà du contenu, il faut le créer avant de déclarer le chemin volume (le système de fichier de docker est très pourri en terme de perf). Donc ici il te faut au moins un volume pour la BDD, un autre pour les médias (pour les statics pas besoin, sauf si tu prévois de les faire servir par un autre container nginx)
RUN: (même si je comprends que là c'est en mode test rapide)
je pense que c'est pas vraiment bien d'avoir deux commandes en parallèle dans un container. Tu fais plutôt un script qui devient l'entrypoint et qui permet de lancer chaque commande (ok c'est acceptable en première instance)
ce n'est pas top non plus de lancer le migrate ou le populate au démarrage, c'est des choses qui sont faite normalement à la livraison, pas au lancement.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.