web-dev-qa-db-fra.com

Comment ignorer les dossiers à envoyer dans le contexte de construction Docker

Je suis confronté à un problème de contexte de construction de grands dockers en raison de la structure de mon projet. Dans mon répertoire racine, j'ai un dossier lib pour le code commun et des dossiers de micro-services. Maintenant, je veux construire pour miscroservice1 pour inclure uniquement le dossier lib et ignorer les autres microservices.

J'exécute la commande docker build dans le dossier racine car l'exécution de la commande dans le dossier microservice donne une erreur Chemin d'accès interdit en dehors du contexte de construction

rootFolder
-- lib
-- microservice1/Dockerfile
-- microservice2/Dockerfile
-- microservice3/Dockerfile

J'ai deux solutions mais je n'ai pas essayé pour l'instant

  1. Pour ajouter des liens symboliques pour lib dans mon dossier de microservices
  2. Pour écrire un script pour chaque build de docker afin d'ajouter le dossier lib dans un dossier de microservice spécifique, puis d'exécuter la build de docker.

J'essaie les deux solutions ci-dessus. Quelqu'un peut-il suggérer une meilleure pratique?

3
Ibtesam Latif

Si le seul outil dont vous disposez est Docker, il n'y a pas beaucoup de choix. Le problème clé est qu'il n'y a qu'un seul .dockerignore fichier. Cela signifie que vous devez toujours utiliser le répertoire racine de votre projet comme répertoire de contexte Docker (y compris les sources de tous les services), mais vous pouvez indiquer à Docker quel Dockerfile spécifique à utiliser. (Notez que toutes les directives COPY seront relatives à rootFolder dans ce cas.)

docker build rootFolder -f microservice1/Dockerfile -t micro/service1:20190831.01

Dans de nombreuses langues, il existe un moyen de regrouper la bibliothèque (C .a, .h, et .so des dossiers; Java .jar des dossiers; Python roues; ...). Si votre langue le prend en charge, une autre option consiste à créer la bibliothèque, puis copiez (pas le lien symbolique) la bibliothèque dans l'arborescence de construction de chaque service. En utilisant le format de roue de Python comme exemple:

pip wheel ./lib
cp microlib.whl microservice1
docker build microservice1 -t micro/service1:20190831.01
# Dockerfile needs to
# RUN pip install ./microlib.whl

Une autre variante utile à ce sujet est une construction manuelle en plusieurs étapes. Vous pouvez avoir lib/Dockerfile choisissez une image de base, puis installez la bibliothèque dans cette image de base. Ensuite, chaque service Dockerfile démarre FROM l'image de la bibliothèque et la fait préinstaller. En utilisant une bibliothèque C comme exemple:

# I am lib/Dockerfile

# Build stage
FROM ubuntu:18.04 AS build
RUN apt-get update && apt-get install build-essential
WORKDIR /src
COPY ./ ./
RUN ./configure --prefix=/usr/local && make
# This is a typical pattern implemented by GNU Autoconf:
# it actually writes files into /src/out/usr/local/...
RUN make install DESTDIR=/src/out

# Install stage -- service images are based on this
FROM ubuntu:18.04
COPY --from=build /src/out /
RUN ldconfig
# I am microservice1/Dockerfile
ARG VERSION=latest
FROM micro/lib:${VERSION}
# From the base image, there are already
# /usr/local/include/microlib.h and /usr/local/lib/libmicro.so
COPY ...
RUN gcc ... -lmicro
CMD ...

Il existe également généralement une option (là encore, en fonction de votre langue et de son système de conditionnement) pour télécharger votre bibliothèque intégrée sur un serveur, peut-être celui que vous exécutez vous-même. (A Python pip requirements.txt le fichier peut contenir une URL HTTP arbitraire pour une roue, par exemple.) Si vous faites cela, vous pouvez simplement déclarer votre bibliothèque comme une dépendance ordinaire, et ce problème disparaît.

Laquelle de celles-ci fonctionne le mieux pour vous dépend de votre langue et de votre exécution, et du degré d'automatisation de plusieurs docker build commandes que vous êtes prêt à exécuter.

1
David Maze