Moby: Réinitialiser les propriétés héritées de l'image parent

Créé le 6 janv. 2014  ·  153Commentaires  ·  Source: moby/moby

Lors de la création d'une image, je souhaiterais peut-être réinitialiser certaines de ses propriétés au lieu de les hériter de l'image parent. Il est logique d'hériter de toutes les propriétés par défaut, mais il devrait exister un moyen de les réinitialiser explicitement et sélectivement lorsque cela est logique.

Il s'agit d'une solution plus générique à #2210 qui ne traite que expose .

arebuilder kinenhancement statuneeds-attention

Commentaire le plus utile

J'aimerais certainement avoir un moyen de supprimer les points VOLUME hérités des images parents.

Par exemple, supposons que j'aie une image principale pour une application qui utilise un point de montage externe pour les données persistantes, mais que je souhaite également une image basée sur celle-ci et pré-remplie avec des données de test à la place. En l'état, je ne peux pas le faire si l'image parente utilisait VOLUME car toute modification/ajout à ces répertoires, même si ces modifications se produisent lors d'une construction de docker, sont perdues lors de la validation.

Tous les 153 commentaires

Suggestions bienvenues pour la syntaxe.

Le mieux que je puisse trouver est des commandes correspondantes comme UNVOLUME ou plus génériquement -VOLUME (mais cela ajouterait plus de confusion, et pourrait même créer l'idée fausse que +VOLUME devrait fonctionner, et devrait fonctionner différemment de seulement VOLUME ).

Je veux vraiment une telle chose (surtout pour les VOLUME). C'est aussi un peu désorientant que des choses comme VOLUME s'appliquent au suivi des lignes RUN, mais pas des choses comme ENTRYPOINT. Parfois, c'est très utile, et parfois non, mais une "désactivation de l'instruction X précédente" générique pourrait très bien résoudre les problèmes liés à cela.

Existe-t-il une solution de contournement pour cela en attendant? J'étends une image avec un ENTRYPOINT (https://github.com/jagregory/pandoc-docker/blob/master/Dockerfile) et je dois supprimer le point d'entrée. J'ai essayé d'utiliser ce qui suit dans mon Dockerfile :

FROM jagregory/pandoc
ENTRYPOINT [] # this basically gets ignored (bug?)

FROM jagregory/pandoc
ENTRYPOINT [""] # this will make docker try to exec '' (the empty string)

FROM jagregory/pandoc
ENTRYPOINT ["/bin/sh", "-c"] 
# this will only work if docker run args are quoted:
#   docker run dergachev/pandoc "echo a b c"

Merci!

J'aimerais certainement avoir un moyen de supprimer les points VOLUME hérités des images parents.

Par exemple, supposons que j'aie une image principale pour une application qui utilise un point de montage externe pour les données persistantes, mais que je souhaite également une image basée sur celle-ci et pré-remplie avec des données de test à la place. En l'état, je ne peux pas le faire si l'image parente utilisait VOLUME car toute modification/ajout à ces répertoires, même si ces modifications se produisent lors d'une construction de docker, sont perdues lors de la validation.

Juste pour mettre à jour le commentaire de CMD [] et ENTRYPOINT [] fonctionnaient la dernière fois que je les ai testés récemment, et devraient toujours fonctionner (tout le reste serait mûr pour le dépôt de bogues).

Vous pouvez réinitialiser toutes les commandes à option unique via

ENTRYPOINT []
CMD []
USER 0
WORKDIR /

Cela devrait laisser les métadonnées non réinitialisables restantes sous la forme ENV , VOLUME , EXPOSE et peut-être ONBUILD .

(Ceci vient du #8709)

Si j'exposais les sockets 9000-9002 dans le parent, mais que je devais ne pas exposer 9001 dans l'enfant, je devrais alors écrire dans le style "unsetting"

EXPOSER
EXPOSE 9000
EXPOSE 9002

qui fonctionnerait mais

NON EXPOSÉ 9001

a l'air plus sympa.

Un avantage étant que cela n'affecte aucun EXPOSE plus haut dans la chaîne d'héritage, que je souhaiterais peut-être ajouter plus tard.

+1 @ codeon-nat

Cela a été discuté dans #8177, nous fermons ceci pour un manque de cas d'utilisation du monde réel.

Pourquoi est-ce fermé? Il y avait 9 personnes qui ont commenté ici. Je pense que ce serait une chose vraiment utile à avoir. Les cas d'utilisation du monde réel peuvent facilement s'appuyer sur des images existantes. Parfois, vous voulez ajouter une propriété, parfois vous voulez la supprimer. C'est normal.

Je suis d'accord, par exemple, j'étends l'image nginx pour un déchargeur SSL et je veux UNEXPOSE 80 mais je laisse 443 .

Être capable de ne pas exposer les ports est assez critique si vous souhaitez exécuter plusieurs instances de, par exemple, nginx.

Peu importe, c'était juste une mauvaise configuration de mon côté.

(15 avril : « Aucun cas d'utilisation dans le monde réel » Je suis surpris que vous ne puissiez pas en imaginer au moins un et j'ai fermé cela)

J'ai une image de base qui expose des volumes ou des ports pour les logiciels facultatifs, puis à partir de celle-ci dans un autre Dockerfile pour créer une image qui ne devrait pas exposer ce qu'elle ne veut pas, ni même des choses qu'elle a désinstallées de l'ancêtre. Pourquoi ne voudrions-nous PAS pouvoir supprimer ces paramètres ?

J'ai aussi un cas d'utilisation pour cela. Je veux pouvoir créer une image contenant un instantané de la base de données, mais tous les packages mysql ont VOLUME /var/lib/mysql définis. Ce serait bien de pouvoir désactiver le volume, les modifications apportées à la base de données dans mon Dockerfile resteront fidèles à l'image.

La seule autre option est de recréer complètement une image mysql personnalisée, mais cela semble en quelque sorte un gaspillage car de nombreuses autres personnes ont déjà mis en place de meilleurs serveurs mysql par défaut que moi.

Ajout d'un cas d'utilisation supplémentaire - j'hérite de l'image officielle de RabbitMQ, mais je souhaite uniquement exposer les ports Websocket (80 et 443) et non le port AMQP par défaut (5672). On dirait que cela devrait être une chose assez raisonnable à vouloir faire?

Ajout d'un autre cas d'utilisation. Je souhaite créer un environnement de test git à l'aide de l'image gogs, mais il est fastidieux de conserver les données car elles sont toutes stockées dans un volume. Ce serait formidable si je pouvais simplement DÉVOLUMER le volume et construire mon image après avoir configuré l'environnement.

+1

héritant du php officiel et souhaitez utiliser des sockets au lieu de ports, vous devez donc supprimer le port 9000 exposé

Quiconque a utilisé Docker à titre non trivial aura trouvé ces limitations avec les conteneurs hérités.

@shykes @icecrime comment est-ce maintenant fermé? Est-ce trop difficile à résoudre avec la syntaxe actuelle et le besoin d'une compatibilité descendante ? Quel est le plan?

+1 - cas d'utilisation du monde réel pour le remplacement d'EXPOSER ici.

Étant donné que cela dure depuis plus de 3 ans (problème trouvé remontant à 2013), quand pourrons-nous supprimer les ports exposés ?

+1. besoin de pouvoir "UNEEXPOSER" les ports nginx par défaut 80 et 443.

Pour les personnes ici qui demandent UNEXPOSE ; l'instruction EXPOSE ne donne qu'un indice sur les ports exposés par le conteneur, mais n'expose pas réellement ces ports ; vous devez _publier_ ces ports ( -p / -P ) pour les exposer sur l'hôte. En d'autres termes; omettre l'instruction EXPOSE d'un Dockerfile n'a _pas_ d'effet direct sur l'image (vous pouvez toujours, par exemple, atteindre le "port 80" du conteneur).

De plus, si vous souhaitez exposer des ports supplémentaires, exécutez simplement le service dans le conteneur sur ces ports, et cela fonctionnera.

C'est vrai, mais si vous utilisez -P (pour exposer tous les ports) et que votre image de base expose un port que vous ne souhaitez plus exposer, vous êtes bloqué. Vous devrez utiliser -p et répertorier tous les autres ports.

@thaJeztah c'est bon à savoir. Néanmoins, quel est l'inconvénient d'ajouter UNEXPOSE ? Cela me serait utile aussi, ne serait-ce que pour avoir des conteneurs mieux documentés.

@kgx aucun mal (à part une possible augmentation des fonctionnalités), mais UNVOLUME (ou UNSET VOLUME ) est toujours sur ma liste de souhaits personnelle. :-)

Je suis amusé d'avoir rencontré ce problème au cours des 72 premières heures d'essai de Docker. Chaque configuration ou langage pour tout autre outil majeur que j'utilise et qui a une sorte d'héritage a un type de capacité « remplacer le parent ».

Voici un cas d'utilisation : j'utilise l'image docker par défaut pour go-ethereum et je dois pouvoir configurer une version de test qui ne se connectera absolument jamais au monde extérieur. Je dois pouvoir m'y connecter à partir de l'hôte et d'autres conteneurs. Le moyen le plus sûr de le faire est de changer les ports car le programme essaie avec impatience de se connecter aux pairs. Je dois également pouvoir remplacer CMD et ENTRYPOINT pour créer une version "configurer la base de données" de l'image que j'exécute une fois pour créer le volume approprié. Tous ces éléments sont extrêmement difficiles à retirer dans le Dockerfile.

Vous pouvez l'attribuer à une autre adresse IP... Ou lier un autre port hôte. Le dernier point sur le point d'entrée et le cmd de dépassement consiste simplement à les redéfinir.

---Envoyé de Boxer | http://getboxer.com

Le 20 février 2016 à 08:57:00 GMT, barkthins [email protected] a écrit : Voici un cas d'utilisation : j'utilise l'image docker par défaut pour go-ethereum, et je dois pouvoir configurer un test version qui ne se connectera absolument jamais au monde extérieur. Je dois pouvoir m'y connecter à partir de l'hôte et d'autres conteneurs. Le moyen le plus sûr de le faire est de changer les ports car le programme essaie avec impatience de se connecter aux pairs. Je dois également pouvoir remplacer CMD et ENTRYPOINT pour créer une version "configurer la base de données" de l'image que j'exécute une fois pour créer le volume approprié. Tous ces éléments sont extrêmement difficiles à retirer dans le Dockerfile. —Répondez directement à cet e-mail ou consultez-le sur GitHub.

CMD et ENTRYPOINT peuvent être remplacés à l'exécution ; docker run --entrypoint=foo myimage mycmd . La question ici est de savoir s'il est utile d'avoir une image différente, avec un point d'entrée/cmd différent pendant les tests, car vous ne testerez pas l'image réelle qui s'exécutera en production. (juste une note latérale)

d'après ces réponses, il semble que le dockerfile soit déprécié en faveur des options de ligne de commande au moins en ce qui concerne le point d'entrée, cmd, expose et probablement quelques autres. La ligne de commande fait déjà des choses que le Dockerfile ne peut pas faire, donc cela semble être la direction. Si c'est l'intention, alors je déplacerai autant d'informations Dockerfile que possible vers l'instant d'instanciation juste pour réduire la confusion. Est-ce l'intention?

@barkthins non, le Dockerfile n'est pas obsolète. L'utilisation d'un Dockerfile est toujours le moyen habituel de produire une image. En outre, vous pouvez remplacer CMD et ENTRYPOINT dans les images héritées. Mon exemple était de montrer que dans certains cas (par exemple, exécuter une commande alternative sur votre image), vous pouvez les remplacer au moment de l'exécution.

Depuis la page de manuel Dockerfile :

     -- EXPOSE <port> [<port>...]
     The EXPOSE instruction informs Docker that the container listens

sur le
ports réseau spécifiés au moment de l'exécution. Docker utilise ces informations pour
interconnecter les conteneurs à l'aide de liens et _pour configurer le port
redirection sur l'hôte_

  • système.*
    [...]
    L'HISTOIRE
    *Mai 2014, compilé par Zac Dover (zdover chez redhat dot com) basé
    sur docker.com Documentation Dockerfile. *Fév 2015, mis à jour par Brian Goff (
    [email protected])
    pour plus de lisibilité *Sept 2015, mis à jour par Sally O'Malley (
    [email protected])

[mes italiques] semble trompeur (ou du moins ambigu) si ce que vous dites est
vrai.

Le jeu. 28 janv. 2016 à 06:43, Sebastiaan van Stijn <
[email protected]> a écrit :

Pour ces personnes ici qui demandent UNEXPOSE ; l'instruction EXPOSER uniquement
donne un _indice_ quels ports sont exposés par le conteneur, mais ne
en fait _exposez_ ces ports ; vous devez _publier_ ces ports (-p / -P)
pour les exposer sur l'hôte. En d'autres termes; en omettant l'instruction EXPOSE
à partir d'un Dockerfile n'a _pas_ d'effet direct sur l'image (vous pouvez
encore, par exemple atteindre le "port 80" du conteneur).

De plus, si vous souhaitez exposer des ports supplémentaires, faites simplement le
service dans le conteneur exécuté sur ces ports, et cela fonctionnera.

-
Répondez directement à cet e-mail ou consultez-le sur GitHub
https://github.com/docker/docker/issues/3465#issuecomment-176012915 .

Actuellement co-auteur d'un livre sur Docker : obtenez 39% de réduction avec le code 39miell
http://manning.com/miell/?a_aid=zwischenzugs&a_bid=e0d48f62

thaJeztah Mon point et je pense que le point de ce fil est que l'héritage est incohérent. Oui, vous pouvez remplacer ENTRYPOINT et CMD mais EXPOSE ajoute une exposition, vous ne pouvez pas remplacer l'exposition du parent sauf sur la ligne de commande. Je n'ai pas examiné d'autres commandes pour voir s'il y a un troisième comportement. Il n'est pas non plus documenté quelles commandes étendent ou remplacent la commande d'un parent.

@thaJeztah nous avons besoin d'UNEEXPOSE

Il existe plusieurs solutions qui lisent les métadonnées du conteneur et fournissent une configuration en amont supplémentaire. Par example; avec HAPROXY, je dois définir EXCLUDE_PORTS=8080 pour le bloquer en essayant de fournir dynamiquement l'accès à ce port sur mes applications Tomcat.

Les développeurs examinent les ports exposés et font des hypothèses sur le comportement du conteneur. Par exemple, j'ai une image de base qui étend Tomcat (EXPOSE 8080) mais l'image utilise un port différent de celui par défaut (EXPOSE 8888). Si vous ajoutez un serveur Web dans une image composée (par exemple, exécutant NGINX et Tomcat), vous servez du contenu via HTTP (EXPOSE 80 et EXPOSE 443).

Dans ce dernier exemple, vous pouvez vous retrouver avec une image qui s'auto documente comme exposant 8080, 8888, 80 et 443 où seul 80/443 est pertinent.

Ce sont de vrais problèmes comme en témoigne le fait que je dois continuer à expliquer les choses aux développeurs de notre communauté malgré une documentation très spécifique ; qui a besoin de documentation quand on peut juste regarder l'image ? <-- tout le monde quand l'image auto-documente la mauvaise chose.

Il existe des solutions de contournement à ce problème, mais ce sont des solutions de contournement. Est-ce un enjeu architectural majeur ? Pourquoi Docker ne peut-il pas envisager une solution plus élégante à ce problème réel.

Quel est le statut à ce sujet ?

Le statut de

@modius @BillBrower même s'il est fermé, les choses peuvent toujours être reconsidérées; fondamentalement « non est temporaire », mais « oui est éternel » lors de la fusion/mise en œuvre de fonctionnalités, donc s'il y a des préoccupations au sujet d'une fonctionnalité, le bon choix pour les responsables est de dire « non ».

Le PR l'implémentant a été fermé car certains responsables n'étaient pas sûrs de la fonctionnalité et recherchaient des exemples plus réels pour son utilisation ; https://github.com/docker/docker/pull/8177#issuecomment-93587164

Nous fermons ceci car nous sommes pour la plupart en désaccord, mais n'hésitez pas à nous prouver le contraire dans les commentaires et nous pourrons reconsidérer

C'était il y a plus d'un an, alors peut-être que les choses ont changé ; Je rouvrirai ce problème et je le soulèverai lors de la prochaine session des responsables. (Notez qu'en raison de DockerCon et de la version 1.12 en attente, cela peut être légèrement plus long que d'habitude)

Merci, @thaJeztah. Cela a du sens. Je vous remercie d'avoir expliqué la justification de la décision initiale et d'avoir souligné ce que vous devez voir si nous voulons que cela se produise.

Un cas d'utilisation pour la requête _UNVOLUME_

Surtout parce qu'actuellement, lorsque vous utilisez un pilote de volume personnalisé, il s'applique à TOUT le volume du conteneur donné.

J'ai eu le cas avec un pilote de volume EFS : fonctionne bien lorsque je spécifie la liaison de volume au démarrage. Si je ne définis aucune liaison, cela échoue car il essaie de monter le partage NFS à partir d'un UUID généré automatiquement. Cela signifie que je dois fournir une reliure à tous mes volumes, même celui qui m'importe peu, créé par une image parente par exemple.

La seule solution de contournement pour le moment consiste à lier au démarrage tout le volume dont je n'ai pas besoin à un sous-dossier vide du même partage EFS.

Remarque : je ne peux pas utiliser la commande docker volume car tout cela est démarré par Marathon et devrait être utilisable dans une seule commande docker run.

+1 UNEXPOSE requis

+1 pour NON EXPOSÉ

+1 pour NON EXPOSÉ

+1 pour NON EXPOSÉ

+100 pour UNEXPOSE

+9000 pour UNEXPOSE

+∞
Par exemple, j'utilise le référentiel officiel nginx (FROM nginx:stable) , qui contient dans Dockerfile :

EXPOSE 80 443

Mais je veux supprimer dans une autre couche, le port 80. Ex :

UNEXPOSE 80

S'il te plaît!
Ajoutez cette fonctionnalité !!!!

@frekele , si

UNEXPOSER +++
Fonctionnalité très nécessaire !

S'il vous plaît, vous n'avez pas besoin de spammer tout le monde avec des notifications par e-mail et vous n'avez certainement pas besoin d'encombrer la discussion avec tous ces commentaires '+1'. Vous pouvez simplement réagir avec 👍 à la description du problème pour exprimer votre accord.

@underyx c'est
Voir https://github.com/isaacs/github/issues/9#issuecomment -195120703 (tout le fil est bon, mais c'est à peu près au moment où GH a ajouté des réactions).
N'encombrons pas la discussion maintenant ;)
/offtopic .

Nous avons discuté de ce problème lors de la réunion des responsables, et en général, nous sommes d'accord pour recommencer à travailler dessus.

@duglin êtes-vous peut-être intéressé à travailler là-dessus ?

Je ne sais pas si j'ai encore le temps, mais juste pour résumer... sur la base des commentaires ci-dessus, je pense que l'exigence est de s'assurer que les gens peuvent effacer/désactiver les éléments suivants :

EXPOSE  (all or specific one)
ENV  (specific - not sure we need to clear all yet)
LABEL  (ditto)
VOLUME  (all or just specific paths? probably both)
CMD  (possible but only using the json format)
ENTRYPOINT  (possible with json format)

Est-ce que j'ai manqué quelque chose?

+10000 pour UNVOLUME

@duglin Je pense que commencer par ceux qui ne sont actuellement _pas_ possibles, et les plus demandés seraient les meilleurs ( EXPOSE , VOLUME ). Je n'ai pas vu beaucoup de demandes pour les autres (mais pas contre).

Le PR d'origine utilisait UNSET <SOMETHING> , mais a ensuite été remplacé par UN<SOMETHING> . J'ai _personnellement_ aimé le premier plus (plus générique), mais @shykes a préféré UN<SOMETHING> , je ne sais pas si cela a changé.

UNVOLUME serait sympa.

Mon cas d'utilisation : j'utilise l'image mysql et je souhaite valider ma base de données contenue dans le répertoire /var/lib/mysql dans une nouvelle image, mais je ne peux pas car elle est déclarée comme un volume dans le Dockerfile parent.

@thaJeztah Je trouve UNSET <something> plus facile à lire et pas aussi bizarre; pas besoin de commencer à inventer des mots. C'est aussi familier aux gens qui écrivent des scripts. On pourrait aussi faire

UNSET  EXPOSE VOLUME LABEL

Mon exemple,

Je suis en train de mettre en place une installation dokuwiki. L'image que j'ai choisie exposait tous les volumes de configuration potentiels. Ce que je voudrais faire, c'est personnaliser mon installation à partir de cette image de base. Comme les volumes sont exposés, je ne peux pas modifier les fichiers de configuration PHP au moment de la création de l'image.

Je peux modifier l'image de base pour UNVOLUME ces volumes, mais je devrai alors conserver cette image pour toujours...

+1 pour UNEXPOSE :)

+1 pour UNVOLUME ou mieux encore UNSET VOLUME.

+1 pour UNVOLUME. Cela pourrait être utile pour moi en ce moment. Cela pourrait également être utile dans les scénarios universitaires où les étudiants tournent sans se soucier d'avoir à monter des volumes.

sans vous soucier d'avoir à monter des volumes.

Je ne pense pas que ce sera nécessaire pour cela; une définition VOLUME dans un Dockerfile crée automatiquement un volume "anonyme" à partir du contenu à cet emplacement dans l'image.

@duglin , travaillez-vous déjà dessus ? Sinon, je le prendrais et commencerais par le plus demandé (VOLUME et EXPOSER). Fais-moi savoir.

@runcom vas-y - je n'ai pas encore trouvé le temps.

Pour rappel, notons qu'une commande UNENV serait toujours utile, pour désarmer sélectivement les variables d'environnement (par exemple, pour faire correspondre un volume qui vaut UNVOLUME d en même temps). Une variable non définie n'est pas la même chose qu'une variable définie sur vide, en particulier lorsqu'elle est utilisée avec set -ue dans le shell.

Il serait possible de supprimer VOLUME et EXPOSE des images officielles si
ils sont un problème.

Le 28 janvier 2017 à 21h23, "henryptung" [email protected] a écrit :

Pour rappel, notons qu'une commande UNENV serait tout de même utile, pour
unset variables d'environnement de manière sélective (par exemple, pour correspondre à un
volume qui est UNVOLUME en même temps). Une variable non définie n'est pas la
identique à une variable définie sur vide, en particulier lorsqu'elle est utilisée avec set -ue dans
coquille.

-
Vous recevez ceci parce que vous êtes abonné à ce fil.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/docker/docker/issues/3465#issuecomment-275875623 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/AAdcPAKP1tii706MY-8MxVPSFLTFme8Dks5rW7HggaJpZM4BXt2-
.

+1 pour UNVOLUME

+1 pour UNVOLUME

Mon cas d'utilisation pour UNVOLUME :

Utilisation de l'image bibliothèque/worpress dans un scénario S2I où la source du site Web est copiée dans /var/www/html

VOLUME écrase cela en montant un FS vide sur l'image résultante. -> la bibliothèque/wordpress ne peut pas être utilisé.

@groulot En fait, si vous ne montez pas explicitement un volume avec --volume dessus, le contenu de l'image sera copié dans le volume lors de la création du conteneur.

La commande docker run initialise le volume nouvellement créé avec toutes les données qui existent à l'emplacement spécifié dans l'image de base.

https://docs.docker.com/engine/reference/builder/#/volume

Il existe une solution de contournement en utilisant docker save/load, voir http://stackoverflow.com/q/42316614/808723

+1 pour UNVOLUME

Je veux faire écho à la justification de docker ps pour voir ce qui se passe avec leurs conteneurs. Ils verront le port standard répertorié comme étant disponible. Les développeurs sont habitués aux ports standard pour les éléments de leurs environnements locaux ou de test qu'ils ont configurés dans un monde pré-Docker, il est donc difficile d'introduire Docker car ils voient le port standard et pensent qu'il fonctionnera - mais en fait, ils sont ne se connecte pas au conteneur docker.

+1 pour UNVOLUME, UNEXPOSE, UNENV, ...

On dirait que c'est ouvert depuis un moment. Une traction ici?
Je souhaite également utiliser l'image alpine officielle PHP fpm et les sockets UNIX au lieu du port TCP 9000.
Ne peut pas remplacer l'EXPOSE du parent, et préférerait ne pas créer cette image juste pour se débarrasser de l'EXPOSE.

+1

+1

J'adorerais la possibilité de désactiver une commande VOLUME. L'image officielle de Wordpress vide avec force sa base de code complète dans un volume - je préférerais de loin n'avoir qu'un volume pour le répertoire wp-content/uploads afin que le reste de la base de code puisse être intégré à l'image.

Lors du déploiement d'une image sur un cluster kubernetes qui restreint l'accès root, les répertoires VOLUME ne sont pas accessibles, la solution consisterait à écraser les volumes définis dans l'image parent

+1 de moi

Cas d'utilisation pour UNEXPOSE

Supposons que j'ai quatre hôtes docker et que je souhaite exécuter 16 conteneurs maven tomcat qui sont tous par défaut le port interne 8080.

Imaginez maintenant que j'utilise un registraire avec le rancher CNI - qui me verrouille sur le port interne.
https://github.com/gliderlabs/registrator/issues/541#issuecomment-305012416
Cela signifie que je ne peux exécuter qu'un seul port interne 8080 par hôte. (Puisque je dois faire des mappages de ports 8080:8080)

Dans cette situation, le mappage du port interne -> externe de docker ne suffit pas pour résoudre mon problème. J'ai en fait besoin de remplacer le mappage de port interne, de préférence sans reconstruire le conteneur d'origine.

Julian, je ne sais pas comment vous avez un mappage 1 à 1. Pour moi registrateur en tant que
rien à voir avec le routage du trafic, il enregistre et désenregistre simplement
conteneurs en cours d'exécution. Par exemple, je l'utilise d'une manière que le Registrator maintiendra
une instance Etcd en mettant l'IP allouée à Docker et le port exposé dans
là. Ensuite, en utilisant confd, il surveillera une instance Etcd et mettra à jour le nginx
config dans son propre conteneur.
Le sam. 17 juin 2017 à 04:06, Julian Gamble [email protected]
a écrit:

Cas d'utilisation pour UNEXPOSE

Supposons que j'ai quatre hôtes docker et que je veuille exécuter 16 maven tomcat
conteneurs qui sont tous par défaut sur le port interne 8080.

Imaginez maintenant que j'utilise le registre avec le rancher CNI - ce qui me bloque
au port interne.
gliderlabs/registrator#541 (commentaire)
https://github.com/gliderlabs/registrator/issues/541#issuecomment-305012416
Cela signifie que je ne peux exécuter qu'un seul port interne 8080 par hôte. (Depuis que j'ai
pour faire des mappages de ports 8080:8080)

Dans cette situation - le mappage de port interne-> externe de docker n'est pas suffisant
pour résoudre mon problème. J'ai en fait besoin de remplacer le mappage de port interne,
de préférence sans reconstruire le conteneur d'origine.

-
Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/moby/moby/issues/3465#issuecomment-309189149 , ou couper le son
le fil
https://github.com/notifications/unsubscribe-auth/ABrq2QGgY81wbePOBKbkTSjpUSoPIocuks5sE0LCgaJpZM4BXt2-
.

Salut Bradley,

Merci d'avoir regarder ceci. J'utilise registrator en combinaison avec ipsecurity intégré à Rancher. Comme vous pouvez le voir sur le lien ici :
https://github.com/gliderlabs/registrator/issues/541#issuecomment-305012416
La possibilité d'afficher les ports externes dans le registre dans les conteneurs programmés par les éleveurs a été restreinte. Cela signifiait que vous ne pouviez utiliser que les ports internes.

Vous pouvez voir qu'il y a des utilisateurs qui s'inquiètent à la recherche d'une solution ici :
https://forums.rancher.com/t/do-you-kill-registrator/5152

Et une solution proposée ici :
https://github.com/cabrinoob/rancher-registrator
(Ce qui n'était pas faisable pour certaines personnes).

Vous pouvez en trouver plus si vous recherchez sur Google "registrator rancher".

Ils vous recommandent d'exécuter le registraire en mode « interne » - où vous mappez vos ports internes 1:1 à vos ports externes. Cela conduit au problème avec UNEXPOSE - à court de ports internes.

Mon point est que ipsecurity utilisé pour la mise en réseau de conteneurs docker intra-hôte peut conduire à un cas d'utilisation où vous êtes verrouillé dans des ports internes mappés 1:1 sur des ports externes dans docker. Pour cela, vous devez avoir une commande UNEXPOSE .

Merci d'avoir regarder ceci.

Acclamations
julien

3,5 ans se sont écoulés et aucun progrès sur cette question ?...

+10086 pour UNEXPOSE. parfois, l'image parente peut ne pas être officielle, elle utilise des ports non officiels, nous devrions avoir la possibilité d'écraser les ports.

@pumba-lt
Je parie que la raison pour laquelle cela ne voit aucune résolution est qu'ils ne savent pas comment le faire techniquement.

Cela ajoute également de la complexité au langage Dockerfile lorsqu'il existe des solutions de contournement claires. Ne poussez pas autant de configuration dans le Dockerfile parent et laissez-le plutôt pour les images héritées. (aka: arrêtez de rechercher des images aléatoires sur docker hub :D)

Depuis docker 17.05, il existe également une nouvelle façon de faire des builds en plusieurs étapes qui supprime la plupart du besoin de ce problème (il s'agit d'un seul Dockerfile ):

# First import the original image
FROM nginx AS source-image

# Second step of the build, start with an empty image
FROM scratch
# Copy the data from the original image
COPY --from=source-image / /
# Re-define all the config
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]

EDIT : J'ai oublié de dire que la deuxième solution écrase toutes les couches précédentes. Je pense que ce n'est pas grave mais c'est bon à savoir.

@zimbatm - C'est génial !

Je parie que la raison pour laquelle cela ne voit aucune résolution est qu'ils ne savent pas comment le faire techniquement.

Le changement lui-même n'est pas trop compliqué ; une implémentation peut être trouvée dans ce PR ; https://github.com/moby/moby/pull/8177. Il n'y avait pas de consensus à l'époque, mais si vous suivez mon commentaire de janvier; https://github.com/moby/moby/issues/3465#issuecomment -247405438, les choses ont changé et (à moins que les gens n'aient changé d'avis depuis), nous accepterions une contribution pour mettre en œuvre cela.

Quant à savoir pourquoi il n'est pas encore là ; simplement parce que personne n'a eu le temps de commencer à travailler dessus, mais si quelqu'un est intéressé, il sera très probablement accepté.

@zimbatm oui, votre exemple résoudrait le problème direct, sachez simplement qu'il crée également un calque différent et aplatit tous les calques d'image. Bien que cela puisse dans certains cas réduire la taille de l'image, il en résulte également que ces calques ne sont plus partagés avec des images qui utilisent nginx comme parent, ce qui peut entraîner le téléchargement de plus d'images. Par example;

L'image originale de nginx :

$ docker inspect nginx -f '{{json .RootFS.Layers}}' | jq .

[
  "sha256:54522c622682789028c72c5ba0b081d42a962b406cbc1eb35f3175c646ebf4dc",
  "sha256:1c3fae42c5007fd0e70309b5b964eb5d49046562bd425424da734784098894e7",
  "sha256:87823f21b7939eac6e099fa878871a806c1904a7698793edb63bf6e5f5371e1f"
]

Et l'image nginx que vous avez créée ;

$ docker inspect nginx2 -f '{{json .RootFS.Layers}}' | jq .
[
  "sha256:9a71ba430225d4f24e0d57837a71b6b2b68bf88ca7530c0a89c98783c98531b5"
]

Merci pour la mise à jour @thaJeztah

Puis-je répéter ma suggestion d'utiliser

UNSET XXXX

au lieu d'inventer des mots de vocabulaire nouveaux et étranges (ex : UNVOLUME).

Nous pourrions également supprimer plusieurs propriétés sur une ligne de cette façon.

UNSET VOLUME EXPOSE LABEL

Personnellement, je suis d'accord pour faire UNSET faire l'un ou l'autre ne sera probablement pas un grand changement, donc je laisserai cela pour le processus d'examen lorsqu'un PR arrivera

Salut, même si j'utilise FROM pour la deuxième fois, comment puis-je tout conserver de l'image parent, sauf pour ne pas exposer certains des ports exposés dans l'image parent docker ? y a-t-il une résolution officielle à ce sujet, acceptons cela et travaillons ou rejetons

acceptons ceci et travaillons ou rejetons

@rajiff voir mon commentaire ci-dessus https://github.com/moby/moby/issues/3465#issuecomment -313549657 les contributions sont les bienvenues

Le changement lui-même n'est pas trop compliqué ; une implémentation peut être trouvée dans ce PR ; #8177. Il n'y avait pas de consensus à l'époque, mais si vous suivez mon commentaire de janvier; #3465 (commentaire), les choses ont changé et (à moins que les gens n'aient changé d'avis depuis), nous accepterions une contribution pour mettre en œuvre cela.

Alors si le consensus a pu changer, pourquoi ne pas simplement rouvrir le #8177 ?

Donc, si le consensus a pu changer, pourquoi ne pas simplement rouvrir le #8177 ?

Ce PR a été ouvert il y a plus de trois ans ; le code ne s'applique plus

Au lieu d'avoir à utiliser spécifiquement une commande UNsomething,
pourquoi ne pas améliorer la commande FROM et permettre de lister ce dont on veut réellement hériter ?

Nous pourrions utiliser quelque chose comme :
DEPUIS l'image de base (VOLUME, EXPOSER, PORT, ..)
ou si vous le voulez vraiment avec négation :
DEPUIS l'image de base (*, -VOLUME, -EXPOSE)
ou avoir une meilleure syntaxe ;)

Il me semble que tout cela devrait faire partie de la commande FROM en premier lieu.

Modification du volume à partir du Dockerfile : si des étapes de construction modifient les données dans le volume après leur déclaration, ces modifications seront ignorées.

Cela ne semble pas tout à fait vrai. Vous pouvez toujours faire ceci :

VOLUME /avolume/subdir
WORKDIR /avolume
COPY ./Dockerfile /avolume/subdir

Je ne sais pas si cela pourrait être utilisé pour annuler un volume.

Le remplacement de l'image parent/du conteneur ENTRYPOINT ne fonctionne pas dans les dernières versions.

17.09.1-ce version

$ docker run --name=experiment --entrypoint=/bin/bash ubuntu:16.04
$ docker inspect experiment --format "{{.Config.Entrypoint}}"
[/bin/bash]
$ IMAGE=$(docker commit -c "ENTRYPOINT []" experiment)
$ docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[]

depuis la version 17.10.0-ce

$ docker run --name=experiment --entrypoint=/bin/bash ubuntu:16.04
$ docker inspect experiment --format "{{.Config.Entrypoint}}"
[/bin/bash]
$ IMAGE=$(docker commit -c "ENTRYPOINT []" experiment)
$ docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[/bin/bash]

UNSET ENTRYPOINT ne fonctionne pas non plus.
Est-ce un bug ?

@alexey-igrychev pouvez-vous ouvrir un numéro séparé pour cela ? Le problème que vous commentez est une _demande de fonctionnalité_ pour la mise en œuvre des instructions UNSET xx dans le Dockerfile. (L'instruction UNSET n'est pas encore implémentée, c'est donc normal.)

Pour contourner ce problème, l'utilisation de [""] au lieu de [] pour le point d'entrée semble fonctionner ;

IMAGE=$(docker commit -c "ENTRYPOINT [\"\"]" experiment)
docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[]

J'ai également besoin d'un moyen de désactiver le volume, afin de pouvoir créer une image de base de données préchargée avec des tables et des données.
Malheureusement, l'image de base est privée (oracle) et je ne peux donc même pas copier le fichier docker de base car je n'y ai pas accès. Je ne peux que prolonger l'image.
Ce problème a des tonnes de +1 et de cas d'utilisation du monde réel répertoriés, et plusieurs PR ont été créés pour cela, et pourtant les PR ont été fermés. Alors, que devons-nous faire pour obtenir cette fonctionnalité ?

@veqryn depuis la réouverture de ce problème, personne n'a commencé à travailler sur une pull-request ; la demande d'extraction existante ne s'appliquait plus proprement sur la base de code, une nouvelle doit donc être ouverte ; si quelqu'un est intéressé à travailler là-dessus, alors les choses peuvent reprendre.

Voir mes commentaires précédents ; https://github.com/moby/moby/issues/3465#issuecomment-247405438

Nous avons discuté de ce problème lors de la réunion des responsables, et en général, nous sommes d'accord pour recommencer à travailler dessus.

@duglin êtes-vous peut-être intéressé à travailler là-dessus ?

Et https://github.com/moby/moby/issues/3465#issuecomment-313549657

Quant à savoir pourquoi il n'est pas encore là ; simplement parce que personne n'a eu le temps de commencer à travailler dessus, mais si quelqu'un est intéressé, il sera très probablement accepté.

Mon cas d'utilisation vient de docker-compose.yaml : j'aimerais avoir un fichier de composition pour le développement avec des remplacements pour la production qui ajoutent un proxy inverse TLS, le référentiel Maven, prend en charge le PORT 80/443, n'expose pas les ports 80 et 5432 qui le fichier de composition de développement expose. Ou un fichier de composition pour la production avec substitution de développement.

La nature complémentaire de la superposition des fichiers de composition hérités de Dockerfiles complique la conception du système. Ce serait vraiment cool si certains paramètres pouvaient être rétractés, ou si j'avais simplement un conteneur différent construit avec des remplacements actifs. Je ne suis pas pointilleux sur la façon dont cela fonctionne sous le capot par rapport à docker-compose.

Merci @thaJeztah - pourriez-vous s'il vous plaît nous indiquer la ligne de code qui, à votre avis, est le point de départ pour commencer à lire pour voir

Je n'ai pas beaucoup travaillé sur le code du constructeur moi-même, mais les modifications devraient probablement se trouver dans le package https://github.com/moby/moby/tree/master/builder .

Ce numéro a 3 ans ! Est-ce si difficile de se mettre d'accord sur une fonctionnalité si basique, ou est-ce que j'ai raté quelque chose ?

@caruccio oui, il vous manque quelque chose : faites défiler 4 commentaires vers le haut https://github.com/moby/moby/issues/3465#issuecomment -356988520

J'ai également quelques cas d'utilisation (l'un un projet personnel et le second un projet de travail) où je souhaite surcharger une déclaration VOLUME , EXPOSE et ENTRYPOINT d'un image parentale.

Alors que j'ai une solution de contournement pour ENTRYPOINT en définissant simplement un nouveau point d'entrée vide avec ENTRYPOINT [] , et je peux probablement apprendre à vivre en ignorant EXPOSE , ... Je suis en train de gratter ma tête sur la façon de ne pas hériter des définitions VOLUME .

Je viens de rencontrer ce problème dans ma base de code où l'image parente avait un VOLUME, ce qui signifie que toutes mes modifications apportées à ce volume dans une image enfant ont été supprimées. J'ai pensé que je devenais fou pendant 2 jours jusqu'à ce que je trouve enfin mon chemin vers ce problème. S'il vous plaît, quelqu'un pourrait-il mettre en œuvre cela.

Il existe une solution de contournement.

Vous pouvez toujours docker save image -o image.tar , décompresser cette archive, éditer les métadonnées et remballer pour un docker load -i image2.tar . De cette façon, on peut créer une image2 qui ne contient aucune des déclarations VOLUME précédentes.

Comme je dois faire ces étapes assez régulièrement, j'ai créé un petit script pour aider à nettoyer une image tierce. Jetez un œil à docker-copyedit

Travail fantastique @gdraheim ! Une solution réalisable en <250 lignes de python.

@gdraheim wow, c'est super ! Dans le fichier README :

Le souhait de SUPPRIMER TOUS LES VOLUMES est venu du fait que je voulais télécharger une image testée pour les tests locaux où la partie des données devrait également être engagée dans l'historique afin de ramener à la fois le programme et les données à un état défini afin qu'un autre Le test commencera exactement au même point de contrôle.

C'est aussi notre cas d'utilisation.

J'ai étendu docker-copyedit pour couvrir toutes les entrées de métadonnées d'une image, afin qu'il puisse fonctionner sur toutes les propriétés héritées même au-delà des cas problématiques des listes EXPOSE et VOLUME. Ce serait l'utilisateur, le répertoire de travail, les étiquettes, les paramètres d'environnement pour les choses vues souvent. Copier ENTRYPOINT vers CMD est aussi une modification que je fais assez régulièrement. Plus besoin de faire une étape intermédiaire de construction de docker, optez simplement pour

Le temps utilisé par l'équipe Docker pour suivre et ignorer à plusieurs reprises ce problème aurait probablement suffi à le résoudre à la place.

Pouvons-nous maintenant s'il vous plaît rouvrir ceci après évidemment une tonne d'utilisateurs demandant cela ...
ou au moins donner un argument raisonnable contre cela, pas seulement en ignorant tous les cas d'utilisation (je veux aussi annuler l'exposition d'un port et seulement pour obtenir une sortie docker ps plus propre sans putain (80/80/tcp) avant de créer ma propre image .. .. (ce qui est plus difficile pour les Dockerfiles non open source)

La question est toujours ouverte; C'est open source; les contributions sont les bienvenues https://github.com/moby/moby/issues/3465#issuecomment -356988520

Ai-je raison de penser que cela serait corrigé dans moby/buildkit maintenant ? Je vois la plupart de l'infrastructure de commande Dockerfile là-bas.

Je suis aussi fan de UNSET , comme

UNSET EXPOSE 9000

ou

UNSET LABEL foo

Donc, je regarde les commandes qui ont des formes de sous-commande, comme la forme HEALTHCHECK CMD et je remarque que HEALTHCHECK déjà une forme non définie...

HEALTHCHECK NONE

C'est un choix intéressant, mais HEALTHCHECK ne définit également qu'une seule configuration (et remplace la plus récente), il ne permet pas d'en définir plusieurs, comme LABEL , EXPOSE , et VOLUME font.

Je me demande juste comment ceux-ci devraient interagir ou s'il existe un autre type de formulaire NONE qui pourrait fonctionner.

Un moyen de supprimer les ports exposés est vraiment nécessaire pour contrôler ce qui est exposé lors de l'utilisation du réseau hôte.

+1 EXPOSE []

Donc... pour les 5 ans que l'équipe Docker n'a pas pu implémenter l'opérateur UNSET, fantastique

Comme l'a dit @AnthonyMastrean , devrions-nous déplacer ce problème vers le projet moby/buildkit ?

Il y a aussi un PR, bien documenté et testé mais pas de fusion, devrions-nous déplacer/rebaser ce PR aussi ?

Cette fonctionnalité serait vraiment appréciée et résoudrait un problème avec les images basées sur nginx dans Azure.

UNSET , CLEAR , RESET , OVERRIDE , IGNORE serait bien - j'éviterais UNxxx parce que ça 'dupliquerais la liste des clés réservées pour prendre en charge et documenter.

Ce qu'il faut ignorer/réinitialiser peut également être spécifié lors de l'utilisation de FROM , par exemple

FROM nginx:1.13 IGNORE EXPOSE, ENTRYPOINT

Je suggère une autre solution de contournement, en utilisant des versions en plusieurs étapes.
Il copiera tous les fichiers de l'image d'origine vers la nouvelle image, mais sans métadonnées.

FROM postgres as orig

FROM alpine:3.8 as postgres
COPY --from=orig / /
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 5432
CMD ["postgres"]

Je ne peux pas croire que je n'y avais pas pensé. C'est en fait assez bien @kotofos. Vous perdez les couches du conteneur en amont, mais ce n'est pas une perte énorme.

@kotofos Pourquoi pas FROM scratch as postgres ?

@farcaller bonne prise. scratch serait certainement mieux puisque vous écrasez tout le système de fichiers

La dernière fois que je l'ai testé, COPY --from=xxx ... ne préservait pas le système de fichiers
propriété, vous voudrez peut-être faire attention à cette solution de contournement.

@tianon Vous avez raison, mais pour les conteneurs à processus unique, cela ne devrait pas être un problème car vous pouvez utiliser l'indicateur --chown pour définir l'utilisateur que vous exécutez comme dans le conteneur

https://docs.docker.com/engine/reference/builder/#copy

Cela remonte à 2014. Cela fait 5 ans et il semble qu'il n'y aura pas de "désactivation" ou de "réinitialisation" générique pour toutes les propriétés dans un avenir proche. Je privilégie également une approche générique mais il y a juste beaucoup de choses à considérer et vraiment : cela n'arrivera pas de sitôt.

Donc : pouvons-nous au moins obtenir un "UNEXPOSE" pour fermer tous ces ports ouverts ou obtenir au moins le même comportement que pour CMD et ENTRYPOINT (le dernier gagne) ? C'est la propriété « unset » la plus demandée et un risque de sécurité potentiel pour les utilisateurs qui ne sont pas conscients du comportement (non intuitif), compte tenu du comportement « le dernier gagne » des autres commandes.

Je suggère une autre solution de contournement, en utilisant des versions en plusieurs étapes.
Il copiera tous les fichiers de l'image d'origine vers la nouvelle image, mais sans métadonnées.

FROM postgres as orig

FROM alpine:3.8 as postgres
COPY --from=orig / /
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 5432
CMD ["postgres"]

Je voulais ignorer le volume docker pointé par PGDATA afin que son contenu puisse être regroupé avec l'image et non en tant que volume.
Une solution plus légère pour moi consistait simplement à changer la valeur de PGDATA :

FROM postgres:11.2-alpine
ENV PGDATA /var/lib/postgresql/test-data

# stuff that will create all my schemas
COPY create-scripts /docker-entrypoint-initdb.d/

# a weird way to trigger the entrypoint script to run the stuff in docker-entrypoint-initdb.d but not hang after starting postgres
RUN /docker-entrypoint.sh postgres --version

Y a-t-il un avantage à avoir EXPOSE et VOLUME dans les dockerfiles ? Après tout, vous pouvez les définir facilement dans docker run (et dans docker-compose fichiers), avec --expose (ou -p ) et des volumes nommés ou des montages de liaison. J'ai été mordu à cause d'eux plus d'une fois et il n'y a aucun moyen de les réinitialiser (la création d'un nouveau fichier docker n'est pas très viable, surtout lors de l'extension d'images officielles ou d'images créées avec des makefiles). Je les vois comme un anti-modèle et je pense qu'il vaudrait mieux les déprécier .

@lucasbasquerotto EXPOSE est utilisé par des outils tels que gitlab-runner pour détecter si les ports déclarés exposés par l'image sont réellement ouverts ou non. Je suis d'accord que cela devrait être plus un devoir de HEALTHCHECK pour détecter si le conteneur est prêt ou non, mais avoir une liste de ports déclarés peut être utile pour l'automatisation.
VOLUME est nécessaire pour offrir une expérience conviviale d'arrêt/démarrage d'un conteneur et pour que les données soient conservées automatiquement. Encore une fois, je pense que cela peut être résolu d'une autre manière, mais avoir les données inspectables est bon pour l'outillage (et pour les humains aussi dans ce cas).

ps ne défendant pas la syntaxe Dockerfile, je souligne simplement que les anti-modèles ne sont pas causés par les mots-clés eux-mêmes mais plutôt parce que l'écosystème n'avance pas pour résoudre les problèmes qui peuvent survenir dans des cas d'utilisation courants tels que celui-ci, ou comme fournir une image avec un volume déclaré et quelques données de départ dans le volume (par exemple une image mysql avec un schéma préchargé)

@zarelit Je ne sais pas exactement comment fonctionne gitlab-runner , mais je pense qu'il devrait y avoir un moyen de spécifier les ports à vérifier en dehors du Dockerfile (j'ai trouvé un problème qui est probablement dû à cela, car MySQL expose 2 ports mais il ne faut vérifier que le port 3306 : https://gitlab.com/gitlab-org/gitlab-runner/issues/4143). D'après ce que je vois, il n'utilise également que le port exposé du dernier Dockerfile.

À propos de VOLUME , vous pouvez conserver les données avec état à l'aide de volumes nommés ou les monter avec -v dans un répertoire existant (si vous souhaitez conserver les données lors de la recréation d'un conteneur). Je pense également qu'il serait préférable d'utiliser cette approche car le VOLUME à l'intérieur du fichier docker est un peu obscur pour quiconque étend ce fichier docker, et si vous ne savez pas qu'il est là, vous pourriez penser que votre conteneur est reproductible dans différents environnements et que vous pouvez changer de version sans effets secondaires, pour être mordu plus tard car il utilise des données persistantes sous le capot.

Il ne vous permet pas non plus de déplacer des fichiers vers ce répertoire pendant la construction (en supposant que vous ne vouliez pas l'utiliser comme volume, mais il hérite d'un Dockerfile qui définit le répertoire comme un volume, comme wordpress qui définit /var/www/html/ comme VOLUME, et j'avais besoin d'utiliser quelques hacks pour utiliser un autre répertoire).

En utilisant -v vous déclarez explicitement que vous voulez le volume et évitez les surprises indésirables dues à la magie noire de VOLUME dans le Dockerfile.

En outre, cela peut finir par créer de nombreux volumes anonymes :

La définition d'un volume à l'intérieur de l'image indique à docker de stocker ces données séparément du reste du conteneur, même si vous ne définissez pas le volume lorsque vous lancez le conteneur. La façon dont Docker stocke ces données consiste à créer un volume local sans nom. Le nom lui-même est une longue chaîne d'identification unique qui ne contient aucune référence à l'image ou au conteneur auquel elle est attachée. Et à moins que vous ne disiez explicitement à docker de supprimer des volumes lorsque vous supprimez le conteneur, ces volumes restent, il est peu probable qu'ils soient réutilisés.

Source : https://boxboat.com/2017/01/23/volumes-and-dockerfiles-dont-mix/

@lucasbasquerotto Je suis plutôt d'accord avec vous, il y a tous des problèmes de longue date, je pense qu'une dépréciation devrait suivre un chemin où ils ne deviennent pas invalides, ils deviennent informatifs comme... des chemins suggérés que vous pourriez transformer en volume, les ports suggérés qu'un serveur pourrait écouter.

Je pense que la bonne partie du parcours Docker a maintenant été extraite dans la norme OCI et que nous devrions donc écrire de nouveaux outils qui n'ont pas tout cet héritage sur l'épaule.

Pour tous ceux qui le trouvent utile, n'hésitez pas à utiliser les images du docker tugboat.qa . Ce sont des extensions de plusieurs images docker officielles avec des volumes supprimés. Référentiel GitHub minimalement documenté ici où le gros du travail est fait : https://github.com/TugboatQA/images

Y a-t-il un avantage à avoir EXPOSE et VOLUME dans les dockerfiles ? Après tout, vous pouvez les définir facilement dans docker run (et dans docker-compose fichiers), avec --expose (ou -p ) et des volumes nommés ou des montages de liaison. J'ai été mordu à cause d'eux plus d'une fois et il n'y a aucun moyen de les réinitialiser (la création d'un nouveau fichier docker n'est pas très viable, surtout lors de l'extension d'images officielles ou d'images créées avec des makefiles). Je les vois comme un anti-modèle et je pense qu'il vaudrait mieux les déprécier .

De nos jours, de nombreux fournisseurs fournissent leurs applications sous la forme d'une simple image de conteneur et fournissent des fichiers docker avec elle.
Avoir EXPOSE et VOLUME dans ces fichiers permet l'utilisation d'applications simples avec un simple docker run dans le répertoire de l'application. Vous n'avez besoin de rien savoir sur les paramètres attendus par l'application, cela fonctionne avec tous les paramètres par défaut fournis dans le fichier docker.
Alors oui : bien que nous ayons de meilleurs et plus gros canons comme compose ou k8s pour des applications complexes pour des applications simples, les dockerfiles locaux conviennent toujours parfaitement. Et avoir des valeurs par défaut qui fonctionnent rend l'utilisation pratique.

@ m451 Une exécution de docker plus courte peut être préférable à une plus longue (avec plus d'options définies), mais je ne considère pas cela comme un bon argument pour exposer les ports et les volumes dans le dockerfile.

Au lieu de docker run some_image vous pouvez facilement exécuter docker run --expose 3000 -v my_volume:/container/dir some_image et avoir une compréhension claire des ports exposés à l'hôte et des volumes qui persisteront même après la destruction du conteneur.

De plus, c'est une tâche triviale à faire , et vous exposez et mappez les volumes uniquement lorsque vous en avez besoin (vous n'avez peut-être pas besoin de tous les ports exposés dans le fichier docker, ni de tous les volumes définis. S'il est vraiment important d'exposer certains ports ou utiliser un certain volume, il est préférable de le documenter dans le référentiel afin que les gens ne sachent pas seulement ce qui doit être exposé ou mappé, mais pourquoi, après tout, c'est quelque chose qui affectera l'extérieur du conteneur et peut persister après le conteneur est détruit).

S'il se trouve dans le fichier docker, il peut être plus difficile de savoir ce qui se passe et provoquer des surprises inattendues à long terme lorsqu'un volume persiste et que vous ne le savez pas (surtout si un fichier docker est hérité d'un autre, vous ne le savez peut-être pas au préalable qu'un volume est défini à moins que vous n'inspectiez plus en profondeur ce qu'il fait). Je considérerais donc VOLUME et EXPOSE comme mauvais même si ce problème est résolu.

De plus, bien que ce problème ne soit pas résolu (et je n'ai aucune idée du nombre d'années qu'il faudra pour le résoudre, étant donné qu'il est ouvert depuis plus de 5 ans et demi), je n'ai tout simplement AUCUN MOYEN de réinitialiser eux .

Y a-t-il un avantage à avoir EXPOSE et VOLUME dans les dockerfiles ? Après tout, vous pouvez les définir facilement dans docker run (et dans docker-compose fichiers), avec --expose (ou -p ) et des volumes nommés ou des montages de liaison. J'ai été mordu à cause d'eux plus d'une fois et il n'y a aucun moyen de les réinitialiser (la création d'un nouveau fichier docker n'est pas très viable, surtout lors de l'extension d'images officielles ou d'images créées avec des makefiles). Je les vois comme un anti-modèle et je pense qu'il vaudrait mieux les déprécier .

De nos jours, de nombreux fournisseurs fournissent leurs applications sous la forme d'une simple image de conteneur et fournissent des fichiers docker avec elle.
Avoir EXPOSE et VOLUME dans ces fichiers permet l'utilisation d'applications simples avec un simple docker run dans le répertoire de l'application. Vous n'avez besoin de rien savoir sur les paramètres attendus par l'application, cela fonctionne avec tous les paramètres par défaut fournis dans le fichier docker.
Alors oui : bien que nous ayons de meilleurs et plus gros canons comme compose ou k8s pour des applications complexes pour des applications simples et locales, les dockerfiles conviennent toujours parfaitement. Et avoir des valeurs par défaut qui fonctionnent rend l'utilisation pratique.

Je dirais que les vendeurs qui font cela le font par ignorance. Ne pas comprendre les problèmes que cela pose aux personnes qui souhaitent utiliser leur produit dans un environnement de production. Bien sûr, cela permet à quelqu'un de créer plus facilement une instance de test/démo du produit. Mais maintenant, si je veux l'exécuter pour de vrai, je dois cloner/sed leur Dockerfile ou créer le mien juste pour obtenir une image fonctionnelle.

@ m451 Une exécution de docker plus courte peut être préférable à une plus longue (avec plus d'options définies), mais je ne considère pas cela comme un bon argument pour exposer les ports et les volumes dans le dockerfile.

Au lieu de docker run some_image vous pouvez facilement exécuter docker run --expose 3000 -v my_volume:/container/dir some_image et avoir une compréhension claire des ports exposés à l'hôte et des volumes qui persisteront même après la destruction du conteneur.

De plus, c'est une tâche triviale à faire , et vous exposez et mappez les volumes uniquement lorsque vous en avez besoin (vous n'avez peut-être pas besoin de tous les ports exposés dans le fichier docker, ni de tous les volumes définis. S'il est vraiment important d'exposer certains ports ou utiliser un certain volume, il est préférable de le documenter dans le référentiel afin que les gens ne sachent pas seulement ce qui doit être exposé ou mappé, mais pourquoi, après tout, c'est quelque chose qui affectera l'extérieur du conteneur et peut persister après le conteneur est détruit).

S'il se trouve dans le fichier docker, il peut être plus difficile de savoir ce qui se passe et provoquer des surprises inattendues à long terme lorsqu'un volume persiste et que vous ne le savez pas (surtout si un fichier docker est hérité d'un autre, vous ne le savez peut-être pas au préalable qu'un volume est défini à moins que vous n'inspectiez plus en profondeur ce qu'il fait). Je considérerais donc VOLUME et EXPOSE comme mauvais même si ce problème est résolu.

De plus, bien que ce problème ne soit pas résolu (et je n'ai aucune idée du nombre d'années qu'il faudra pour le résoudre, étant donné qu'il est ouvert depuis plus de 5 ans et demi), je n'ai tout simplement AUCUN MOYEN de réinitialiser eux .

D'accord. Définissons donc une manière standard de communiquer les paramètres requis.
S'il n'y en a pas, nous nous retrouverons avec le même gâchis que nous avions dans les anciennes applications : des documents et des formats de documentation spécifiques aux fournisseurs. Certains vous disent quels ports ouvrir, d'autres non. Certains ne vous en disent que la moitié, d'autres vous indiquent les mauvais ports. Certains ne vous disent que le numéro de port mais pas le protocole et ainsi de suite.

Les Dockerfiles ont été un excellent moyen de standardiser ce gâchis.

@ m451 Je suis d'accord avec vous là-dessus, mais il est bon de considérer que le simple fait d'exposer un port ne transmet pas d'informations utiles. Quel type de données/connexions attend le port exposé ? S'il y a plusieurs ports, que fait chaque port ?

Si vous souhaitez conserver les données, vous souhaitez qu'elles soient montées sur un volume nommé ou à un emplacement sur l'hôte, VOLUME ne vous aide pas. Si vous souhaitez que les données temporaires soient stockées avec plus de performances, VOLUME vous aide (c'est le seul cas où VOLUME peut être utile). L'écriture dans le conteneur est plus lente car elle utilise la stratégie de copie sur écriture . Mais encore une fois, mapper le volume lors de l'exécution du docker évite également CoW (vous n'avez pas besoin de VOLUME), le seul inconvénient est que votre instruction est plus longue et vous devez connaître le chemin (mais ce n'est que si vous avez une performance dégradée en raison à vache).

L'utilisation de VOLUME et EXPOSE comme type de documentation ne justifie pas une mauvaise (ou l'absence d'une) documentation . Et cela peut aussi (et va probablement) nuire à certains consommateurs de l'image.

@ m451 Je suis d'accord avec vous là-dessus, mais il est bon de considérer que le simple fait d'exposer un port ne transmet pas d'informations utiles. Quel type de données/connexions attend le port exposé ? S'il y a plusieurs ports, que fait chaque port ?

Correct. L'idée du trou des ports d'une seconde. la perspective est dépassée. Pourtant : ici, nous essayons de définir quels ports doivent être ouverts et quels ports peuvent rester fermés et de comprendre quelles données sont échangées sur chaque port. HTTPS est devenu un wrapper pour à peu près tout aujourd'hui et à part l'auteur du code, normalement, personne ne sait exactement quelles données sont transférées sur un port particulier. Et même alors, cela peut changer à chaque mise à jour.

Dans RL, vous ne vous souciez pas des données / informations transportées sur quel port, à part cela, vous finissez par dépanner l'application. Vous décidez de faire confiance à l'application. Donc, si l'application ouvre les ports X et Y, vous lui faites également confiance.
Pour les opérations quotidiennes standard, il est bon de simplement démarrer une application et cela fonctionne immédiatement (valeurs par défaut sécurisées supposées).
Les conteneurs sont devenus une forme d'applications d'emballage pour les faire fonctionner immédiatement.

Cela dit, je suis d'accord que les bons docs sont importants. Pourtant, dans RL, personne ne veut lire des documents pendant des heures juste pour savoir quels ports ouvrir. Cela n'apporte aucun avantage pour les tâches opérationnelles quotidiennes.

Ma part du gâteau.

L'utilisation de VOLUME dans le Dockerfile ne vaut rien . Si un utilisateur a besoin de persistance, il s'assurera de fournir un mappage de volume lors de l'exécution du conteneur spécifié. Il était très difficile de déterminer que mon problème de ne pas pouvoir définir la propriété d'un répertoire (/var/lib/influxdb) était dû à la déclaration VOLUME dans le Dockerfile d'InfluxDB. Sans un type d'option UNVOLUME , ou sans débarrasser complètement , je ne peux pas changer quoi que ce soit en rapport avec le dossier spécifié. C'est loin d'être idéal, surtout lorsque vous êtes soucieux de la sécurité et que vous souhaitez spécifier un certain UID, l'image doit être exécutée en tant que , afin d'éviter qu'un utilisateur aléatoire, avec plus d'autorisations que nécessaire, n'exécute un logiciel sur votre hôte.

Il devrait y avoir un moyen de remplacer ces directives VOLUME lors de l'extension des images pour la personnalisation de l'utilisateur. Ma seule solution pour le moment est de recréer complètement l'image moi-même, rendant l'intégralité du _Dockerfile FROM_ dynamique inutile.

DE Nginx:dernier
après le déploiement sur heroku, le port 80 a été exposé par nginx, mais cela ne sera pas autorisé par heroku, alors que puis-je faire ? copiez tous les fichiers docker de nginx et supprimez le fichier EXPOSE 80 ?

Je n'écrirai rien de nouveau... mais ce serait très bien de remplacer la directive EXPOSE.

Partager ceci - https://github.com/gdraheim/docker-copyedit/blob/master/docker-copyedit.py (pas ma création, pour être clair, merci @gdraheim !)

Cela m'a aidé à supprimer un volume d'un conteneur postgres défini dans le fichier docker avec la commande :

python docker-copyedit.py FROM postgres:11.5-alpine INTO postgres:11.5-alpine remove volume /var/lib/postgresql/data

Semble avoir fait le travail sans endommager le conteneur, pris l'image d'origine, l'adapter, créer une nouvelle image sans le volume (selon le docker inspect exécuté sur un conteneur créé à partir de l'image ajustée), non utilisé pour autre chose, mais le git README permet une variété d'opérations, c'est-à-dire

 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     REMOVE PORT 4444
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     remove port ldap and rm port ldaps
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     remove all ports
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     add port ldap and add port ldaps

LABEL est une autre « propriété » (pas encore mentionnée) qui pourrait utiliser la capacité de « désactiver »

Comme mentionné dans ce post SO : https://stackoverflow.com/questions/50978051/how-do-i-unset-a-docker-image-label

Un autre cas d'utilisation pour réinitialiser/supprimer VOLUME des images en amont :

Je travaille sur l'extension d'une image de base de données Oracle mais elle a un volume sur /opt/oracle/oradata . Dans l'image Oracle par défaut, la base de données est créée au démarrage du conteneur et écrit sur ce volume. Mais cela oblige le conteneur à avoir besoin de 25 minutes pour le premier démarrage, ce qui n'est pas acceptable. Je travaille donc sur une image où la base de données est créée lors de la création de l'image, mais je dois donc supprimer le VOLUME /opt/oracle/oradata car ma base de données est créée mais lorsque je démarre le conteneur, le système /opt/oracle/oradata fichiers

Je travaille sur l'extension d'une image de base de données Oracle mais elle a un volume sur /opt/oracle/oradata .

Exactement mon cas d'utilisation aussi. Je voudrais générer une base de données enfichable pré-allouée que d'autres peuvent extraire de notre registre Docker privé... mais le volume est manquant. Je vais devoir creuser plus profondément et décider de la solution de contournement la moins laide.

Je l'ai résolu comme suit :

J'ai utilisé docker-copyedit pour supprimer le volume, puis j'ai écrit un script bash pour créer la base de données (vous pouvez regarder les scripts de démarrage d'oracle pour voir comment c'est fait). Désormais, avec le PDB préconfiguré, il ne faut que 25 secondes pour lancer un conteneur à partir de l'image. Mais l'image devient vraiment grande.

Une meilleure approche serait-elle d'étendre la spécification de docker existante pour inclure un concept de variables d'environnement persistantes / option de remplacement, telle que;

par exemple mon projet basé sur l'image de tomcat en amont :

--ENV CATALINA_HOME /quel/autre/chemin
DE tomcat:8.5.54-jdk8-openjdk
...

Lorsqu'un ENV est déclaré avec -- il doit être élevé à un statut persistant et conserver la valeur déclarée / remplacer toute valeur rencontrée pour cette variable plus tard dans la chaîne de traitement du Dockerfile.

--ENV = à partir de ce point dans le Dockerfile.

Par conséquent, cela pourrait être utilisé au début d'un Dockerfile si vous vouliez qu'il ait la priorité sur toute autre rencontre de la même variable, comme dans les versions à plusieurs étapes. Permettrait également une flexibilité en fonction de l'endroit où dans le Dockerfile il a été placé pour que les références plus élevées dans le fichier soient indépendantes.

N'aurait pas besoin d'un UNVOLUME alors car l'approche correcte serait que VOLUME soit déclaré avec une référence ENV que quelqu'un d'autre pourrait remplacer.

par exemple

ENV PROJ_VOL /quel/chemin
VOLUME $PROJ_VOL

On dirait que ENTRYPOINT [] et ENTRYPOINT [""] invalident tous les deux le cache sur chaque build lorsqu'ils n'utilisent pas BuildKit. Simple Dockerfile à démontrer :

FROM jrottenberg/ffmpeg:4.3-alpine311 as base

ENTRYPOINT []

RUN echo "HERE!"

Les étapes 2 et 3 n'utiliseront _jamais_ le cache. Voici ma solution de contournement :

FROM jrottenberg/ffmpeg:4.3-alpine311 as base

ENTRYPOINT ["/usr/bin/env"]

RUN echo "HERE!"

Je n'arrive pas à reproduire un échec de cache sur votre premier pattern : :confused:

$ cat Dockerfile
FROM alpine:3.12
ENTRYPOINT []
RUN echo 'HERE!'

$ docker build .
Sending build context to Docker daemon  17.25MB
Step 1/3 : FROM alpine:3.12
 ---> a24bb4013296
Step 2/3 : ENTRYPOINT []
 ---> Running in d921be2e563d
Removing intermediate container d921be2e563d
 ---> 7801c649d895
Step 3/3 : RUN echo 'HERE!'
 ---> Running in 9e2ca2cf1f9f
HERE!
Removing intermediate container 9e2ca2cf1f9f
 ---> d398fdd442b1
Successfully built d398fdd442b1

$ docker build .
Sending build context to Docker daemon  17.25MB
Step 1/3 : FROM alpine:3.12
 ---> a24bb4013296
Step 2/3 : ENTRYPOINT []
 ---> Using cache
 ---> 7801c649d895
Step 3/3 : RUN echo 'HERE!'
 ---> Using cache
 ---> d398fdd442b1
Successfully built d398fdd442b1

Je pense que vous devez utiliser une image qui définit ENTRYPOINT . Essayez d'utiliser l'image que j'ai faite ou mysql .

Oh intéressant - je peux reproduire en utilisant mysql:8.0 . Bug solide ! :+1:

Cette page vous a été utile?
0 / 5 - 0 notes