Comment utiliser python-ldap en Production ?
Lors de mes développement je devais m’interconnecter a un ldap pour inserer/verifier des groupes depuis mon API (Fastapi ❤). Pour cela rien de mieux que d’utiliser python-ldap.
Le hic c’est quand on souhaite conteneuriser l’app!
On commence par crée le Dockerfile (dans le style de cet article).
FROM python:3.9.2 AS ldap-build
RUN apt-get update -y && \
apt-get install -y libsasl2-dev python-dev libldap2-dev libssl-dev && \
python -m pip wheel --wheel-dir=/tmp python-ldap==3.3.1
FROM python:3.9.2
COPY --from=ldap-build /tmp/*.whl /tmp
RUN python -m pip install /tmp/*.whl
On build et là surprise la taille de l’image est juste énorme 1Go. Le scan de l’image dans jfrog-xray est pas fameux. Best pratices sur Docker:
- multistage
- limiter le nombre de layer
C’est déjà le cas dans notre Dockerfile… Le problème c’est que l’image de base python:3.9.2 est trop volumineuse. Pour résoudre ça on a plusieurs choix :
- Ubuntu LTS
- Debian Buster
- lightweight distros (Alpine)
- Distroless image (Google)
Je vais pas me lancer dans un comparatif (deja fait ici !) mais je vais résumer un peu mes attentes:
- Ne pas passer trop de temps a builder l’image
- Image pas trop volumineuse
- Adapté pour l’environnement de production
- Réduire au maximun la surface d’attaque de l’image
- Profiter de fonctionnalité avancé de python dans les dernières versions
Quand le drame arrive !
Dockerfile distroless (exemple de base)
FROM debian:buster-slim AS build
RUN apt-get update && \
apt-get install --no-install-suggests --no-install-recommends --yes libsasl2-dev python-ldap libldap2-dev libssl-dev python3-venv &&
python3 -m venv /venv && \
/venv/bin/pip install --upgrade pip && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*FROM build AS build-venv
COPY requirements.txt /requirements.txt
RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txtFROM gcr.io/distroless/python3-debian10
COPY --from=build-venv /venv /venv
COPY . /app
WORKDIR /app
ENTRYPOINT ["/venv/bin/python3", "app.py"]
Le problème c’est qu’il y a des dependances systemes a injecter dans l’image distroless et la j’ai beau demander a google il sait pas… J’ai trouvé un sujet similaire ici sans réponse :-( .
Dans la FAQ de python-ldap
Q: During build there are warning messages displayed telling Lib/ldap.py and Lib/ldap/schema.py are not found:
warning: build_py: file Lib/ldap.py (for module ldap) not found
warning: build_py: file Lib/ldap/schema.py (for module ldap.schema) not found
A:
ldap
andldap.schema
are both module packages (directories containing various sub-modules). The messages above are falsely produced by DistUtils. Don’t worry about it.
Q: While importing module ldap
, some shared lib files are not found. The error message looks similar to this:
ImportError: ld.so.1: /usr/local/bin/python: fatal: liblber.so.2: open failed: No such file or directory
A1: You need to make sure that the path to
liblber.so.2
andlibldap.so.2
is in yourLD_LIBRARY_PATH
environment variable.A2: Alternatively, if you’re on Linux, you can add the path to
liblber.so.2
andlibldap.so.2
to/etc/ld.so.conf
and invoke the commandldconfig
afterwards.
Je ne suis pas un spécialiste de l’image de base de debian… comment trouver les fameux fichiers a copier ?
La réponse est sur le site officiel de debian :-)
https://debian.pkgs.org/10/debian-main-amd64/libldap2-dev_2.4.47+dfsg-3+deb10u6_amd64.deb.html
Il suffit de copier le path de la lib vers l’image distroless !
Solution Finale
FROM debian:buster-slim AS build
RUN apt-get update && \
apt-get install --no-install-suggests --no-install-recommends --yes libsasl2-dev python-ldap libldap2-dev libssl-dev python3-venv && \
python3 -m venv /venv && \
/venv/bin/pip install --upgrade pip && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
FROM build AS build-venv
COPY requirements.txt /requirements.txt
RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txt
FROM gcr.io/distroless/python3-debian10
COPY --from=build-venv /venv /venv
COPY --from=build-venv /usr/lib/x86_64-linux-gnu/ /usr/lib/x86_64-linux-gnu/
ENV LD_LIBRARY_PATH="/usr/lib"
COPY app /app
WORKDIR /app
EXPOSE 80
ENTRYPOINT ["/venv/bin/python3", "main.py"]
Disponible sur ce repo git !
La taille de l’image est de 161 Mb (ça reste beaucoup…)
Une dernière astuce pour diminuer la taille de l’image c’est de builder avec docker-slim. On arrive a une taille d’image de 56.9MB !
Merci d’avoir lu jusqu’a la fin :-)