web-dev-qa-db-fra.com

Est-il possible de combiner des images Docker dans un seul conteneur?

J'ai quelques Dockerfiles en ce moment.

L'un est pour Cassandra 3.5, et c'est FROM cassandra:3.5

J'ai aussi un fichier Docker pour Kafka, mais c'est un peu plus complexe. C'est FROM Java:openjdk-8-fre et il lance une longue commande pour installer Kafka et Zookeeper.

Enfin, j'ai une application écrite en Scala qui utilise SBT. 

Pour ce Dockerfile, il s'agit de FROM broadinstitute/scala-baseimage, ce qui me donne Java 8, Scala 2.11.7 et STB 0.13.9, ce dont j'ai besoin.

Je ne comprends peut-être pas le fonctionnement de Docker, mais dans mon programme Scala, Cassandra et Kafka sont des dépendances et, à des fins de développement, je veux que les autres puissent simplement cloner mon repo avec la variable Dockerfile, puis la construire avec Cassandra Kafka, Scala, Java et SBT ont tout cuit pour pouvoir simplement compiler le source. J'ai cependant beaucoup de problèmes avec cela. 

Comment combiner ces fichiers Dockerfiles? Comment créer simplement un environnement avec ces objets cuits?

21
David

Vous ne pouvez pas combiner des fichiers Docker car des conflits peuvent survenir. Ce que vous voulez faire est de créer un nouveau fichier docker ou de créer une image personnalisée.

TL; DR; Si votre conteneur de développement actuel contient tous les outils dont vous avez besoin et qu'il fonctionne, sauvegardez-le en tant qu'image et déposez-le dans un référentiel et créez un fichier docker pour extraire de cette image le référentiel.

Détails: Construire une image personnalisée est de loin plus facile que de créer un fichier de dock en utilisant une image publique, car vous pouvez stocker tous les hacks et mods dans l'image. Pour ce faire, démarrez un conteneur vide avec une image Linux de base (ou broadinstitute/scala-baseimage), installez tous les outils nécessaires et configurez-les jusqu'à ce que tout fonctionne correctement, puis enregistrez-le (le conteneur) sous forme d'image. Créez un nouveau conteneur à partir de cette image et testez pour voir si vous pouvez construire votre code par dessus via docker-compose (ou comme vous voulez le faire/le construire). Si cela fonctionne, vous avez une image de base de travail que vous pouvez télécharger sur un dépôt pour que d'autres puissent la récupérer.

Pour créer un fichier docker avec une image publique, vous devez placer tous les hacks, les mods et la configuration sur le fichier docker lui-même. Autrement dit, vous devrez placer chaque ligne de commande que vous avez utilisée dans un fichier texte et réduire le nombre de piratages, de mods et de configurations dans des lignes de commande. À la fin, votre fichier de dock créera automatiquement une image. Vous n'avez pas besoin de stocker cette image dans un référentiel. Tout ce que vous avez à faire est de donner aux autres le fichier de dock et ils peuvent faire pivoter l'image vers leur propre menu de base.

Notez qu'une fois que vous avez un fichier docker en état de marche, vous pouvez le modifier facilement, car il créera une nouvelle image à chaque fois que vous utiliserez le fichier docker. Avec une image personnalisée, vous pouvez rencontrer des problèmes pour lesquels vous devez reconstruire l'image en raison de conflits. Par exemple, tous vos outils fonctionnent avec openjdk jusqu'à ce que vous en installiez un qui ne fonctionne pas. Le correctif peut impliquer de désinstaller openjdk et d’utiliser celui d’Oracle, mais toute la configuration que vous avez faite pour tous les outils que vous avez installés est défectueuse.

11
Hin Fan Chan

Vous pouvez, avec la fonctionnalité multi-stage builds introduite dans Docker 1.17

Regarde ça:

FROM golang:1.7.3
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM Alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=0 /go/src/github.com/alexellis/href-counter/app .
CMD ["./app"]  

Construisez ensuite l'image normalement:

docker build -t alexellis2/href-counter:latest

De: https://docs.docker.com/develop/develop-images/multistage- build/

Le résultat final est la même image de production minuscule qu'auparavant, avec une réduction significative de la complexité. Vous n'avez pas besoin de créer d'images intermédiaires ni d'extraire d'artefacts sur votre système local.

Comment ça marche? La deuxième instruction FROM commence une nouvelle étape de construction avec Alpine: la dernière image comme base. La ligne COPY --from = 0 copie uniquement l'artefact construit de l'étape précédente dans cette nouvelle étape. Le SDK Go et tous les artefacts intermédiaires sont laissés et non enregistrés dans l'image finale.

25
Mohammed Noureldin

Oui, vous pouvez transformer un grand nombre de logiciels en une seule image Docker ( GitLab fait ceci, avec une image incluant Postgres et tout le reste), mais generalhenry a raison - Ce n'est pas la façon typique d'utiliser Docker.

Comme vous le dites, Cassandra et Kafka sont dependencies pour votre application Scala, elles ne font pas partie de l'application, elles n'appartiennent donc pas toutes à la même image. 

Devoir orchestrer de nombreux conteneurs avec Docker Compose ajoute une couche admin supplémentaire, mais cela vous donne beaucoup plus de flexibilité:

  • vos conteneurs peuvent avoir différentes durées de vie. Ainsi, lorsque vous devez déployer une nouvelle version de votre application, il vous suffit de lancer un nouveau conteneur d'applications, vous pouvez laisser les dépendances en cours d'exécution;
  • vous pouvez utiliser la même image d'application dans n'importe quel environnement, en utilisant différentes configurations pour vos dépendances - par exemple. dans dev, vous pouvez exécuter un conteneur Kafka de base et, dans prod, le regrouper sur de nombreux nœuds, votre conteneur d'application est identique;
  • vos dépendances peuvent également être utilisées par d'autres applications - afin que plusieurs consommateurs puissent s'exécuter dans des conteneurs différents et que tous travaillent avec les mêmes conteneurs Kafka et Cassandra;
  • plus toute l'évolutivité, la journalisation, etc. déjà mentionnées.
4
Elton Stoneman

Vous ne pouvez pas combiner les images du menu fixe dans un conteneur. Voir les discussions détaillées dans le numéro Moby, Comment combiner plusieurs images en une seule via Dockerfile .

Pour votre cas, il est préférable de ne pas inclure les images complètes de Cassandra et Kafka. L'application n'aurait besoin que du pilote Cassandra Scala et du pilote Kafka Scala. Le conteneur doit inclure uniquement les pilotes.

1
CloudStax

Docker ne fusionne pas les images, mais rien ne vous empêche de combiner les fichiers docker, si disponibles, et de les insérer dans une grosse image que vous auriez besoin de construire. Il y a des moments où cela a du sens, cependant, comme pour l'exécution de plusieurs processus dans un conteneur, la plupart des dogmes de Docker indiquent que c'est moins souhaitable, en particulier avec l'architecture de microservice (cependant, les règles doivent-elles être enfreintes?)

1
Amos Folarin