Compose: Exécuter une commande après l'exécution

Créé le 5 août 2015  ·  131Commentaires  ·  Source: docker/compose

Salut,

Il sera très utile d'avoir quelque chose comme "onrun" dans le YAML pour pouvoir exécuter des commandes après l'exécution. Similaire à https://github.com/docker/docker/issues/8860

mongodb:
    image: mongo:3.0.2
    hostname: myhostname
    domainname: domain.lan
    volumes:
        - /data/mongodb:/data
    ports:
        - "27017:27017" 
    onrun:
        - mongodump --host db2dump.domain.lan --port 27017 --out /data/mongodb/dumps/latest
        - mongorestore -d database /data/mongodb/dumps/latest/database

Après le démarrage de mongodb, il videra db2dump.domain.lan et le restaurera.

Quand je vais arrêter puis démarrer le conteneur, la partie onrun ne sera pas exécutée pour préserver l'idempotence.

EDIT 15 juin 2020

5 ans plus tard, Compose ne veut pas "standardiser" les spécifications,
veuillez vérifier https://github.com/compose-spec/compose-spec/issues/84

Commentaire le plus utile

Donc, pour gérer mon docker, vous me proposez d'utiliser un Script ou un Makefile. Alors pourquoi compose a été créé
? Nous pouvons gérer, mettre à l'échelle etc. un conteneur avec un script || dockerfile?

Ok, je prends cet exemple, c'est ce que j'ai utilisé pour déployer mon environnement de test d'application dans le processus CI.

rabbitmq:
    image: rabbitmq:3.5.1-management
    environment:
        RABBITMQ_NODENAME: rabbit
    hostname: rabbitmq
    domainname: domain.lan
    volumes:
        - /data/rabbitmq/db:/var/lib/rabbitmq
    ports:
        - "5672:5672" 
        - "15672:15672"
        - "25672:25672"
        - "4369:4369"

mongodb:
    image: mongo:3.0.2
    hostname: mongo
    domainname: domain.lan
    volumes:
        - /data/mongodb:/data
    ports:
        - "27017:27017" 

appmaster:
    image: appmaster
    hostname: master
    domainname: domain.lan
    environment:
        ...
    ports:
        - "80:80" 
        - "8080:8080"
    links:
        - mongodb
        - rabbitmq

celery:
    image: celery
    hostname: celery
    domainname: domain.lan
    environment:
        ...
    links:
        - rabbitmq

Après le démarrage du conteneur, je dois provisionner mongodb, gérer la file d'attente et le compte dans rabbitmq

Ce que je fais aujourd'hui, c'est un script avec:

#!/bin/bash
PROJECT=appmaster
docker-compose -f appmaster.yml -p appmaster up -d
docker exec appmaster_rabbitmq_1 rabbitmqctl add_user user password
docker exec appmaster_rabbitmq_1 rabbitmqctl add_vhost rabbitmq.domain.lan
docker exec appmaster_rabbitmq_1 rabbitmqctl set_permissions -p rabbitmq.domain.lan password ".*" ".*" ".*"
docker exec appmaster_mongodb_1 mongodump --host mongo-prd.domain.lan --port 27017 --out /data/mongodb/dumps/latest
docker exec appmaster_mongodb_1 mongorestore -d database /data/mongodb/dumps/latest/database

Avec l'instruction onrun , je peux directement faire docker-compose -f appmaster.yml -p appmaster up -d
et le fichier yml devient plus lisible

rabbitmq:
    ...
    onrun:
        - rabbitmqctl add_user user password
        - rabbitmqctl add_vhost rabbitmq.domain.lan
        - rabbitmqctl set_permissions -p rabbitmq.domain.lan password ".*" ".*" ".*"

mongodb:
    ...
    onrun:
        - mongodump --host mongo-prd.domain.lan --port 27017 --out /data/mongodb/dumps/latest
        - mongorestore -d database /data/mongodb/dumps/latest/database

Tous les 131 commentaires

Je pense que cela devrait être des étapes dans le Dockerfile

FROM mongo:3.0.2
ADD data/mongodb/dumps/latest /data/mongodb/dumps/latest
RUN mongorestore -d database /data/mongodb/dumps/latest/database

De cette façon, vous le mettez également en cache lorsque vous reconstruisez.

Merci @dnephin.
Bien sûr, je peux créer un Dockerfile et l'utiliser dans build au lieu d'images, ou je peux utiliser docker exec.
MongoDB n'est qu'un exemple, vous pouvez avoir cet exemple avec mysql et création de compte, ou avec rabbitmq et création de file d'attente, etc.

onrun permettra une flexibilité sur l'orchestration de la composition, compose lira la liste en cours d'exécution et fera docker exec sur chaque élément.

Le fait est que placer des commandes dans docker exec dans docker-compose.yml est inutile lorsque vous pouvez le faire dans le Dockerfile ou dans le script de démarrage du conteneur, ce qui rendra également votre conteneur plus utile lorsque _pas_ exécuté avec Compose.

Vous pouvez également démarrer votre application avec un script shell ou Makefile qui exécute les commandes docker et docker-compose appropriées.

La fonctionnalité ne vaut pas la peine d'être ajoutée à Compose à moins qu'elle n'ajoute une valeur significative par rapport à l'une ou l'autre de celles-ci, et je ne pense pas que ce serait le cas pour les cas d'utilisation que vous avez cités.

Donc, pour gérer mon docker, vous me proposez d'utiliser un Script ou un Makefile. Alors pourquoi compose a été créé
? Nous pouvons gérer, mettre à l'échelle etc. un conteneur avec un script || dockerfile?

Ok, je prends cet exemple, c'est ce que j'ai utilisé pour déployer mon environnement de test d'application dans le processus CI.

rabbitmq:
    image: rabbitmq:3.5.1-management
    environment:
        RABBITMQ_NODENAME: rabbit
    hostname: rabbitmq
    domainname: domain.lan
    volumes:
        - /data/rabbitmq/db:/var/lib/rabbitmq
    ports:
        - "5672:5672" 
        - "15672:15672"
        - "25672:25672"
        - "4369:4369"

mongodb:
    image: mongo:3.0.2
    hostname: mongo
    domainname: domain.lan
    volumes:
        - /data/mongodb:/data
    ports:
        - "27017:27017" 

appmaster:
    image: appmaster
    hostname: master
    domainname: domain.lan
    environment:
        ...
    ports:
        - "80:80" 
        - "8080:8080"
    links:
        - mongodb
        - rabbitmq

celery:
    image: celery
    hostname: celery
    domainname: domain.lan
    environment:
        ...
    links:
        - rabbitmq

Après le démarrage du conteneur, je dois provisionner mongodb, gérer la file d'attente et le compte dans rabbitmq

Ce que je fais aujourd'hui, c'est un script avec:

#!/bin/bash
PROJECT=appmaster
docker-compose -f appmaster.yml -p appmaster up -d
docker exec appmaster_rabbitmq_1 rabbitmqctl add_user user password
docker exec appmaster_rabbitmq_1 rabbitmqctl add_vhost rabbitmq.domain.lan
docker exec appmaster_rabbitmq_1 rabbitmqctl set_permissions -p rabbitmq.domain.lan password ".*" ".*" ".*"
docker exec appmaster_mongodb_1 mongodump --host mongo-prd.domain.lan --port 27017 --out /data/mongodb/dumps/latest
docker exec appmaster_mongodb_1 mongorestore -d database /data/mongodb/dumps/latest/database

Avec l'instruction onrun , je peux directement faire docker-compose -f appmaster.yml -p appmaster up -d
et le fichier yml devient plus lisible

rabbitmq:
    ...
    onrun:
        - rabbitmqctl add_user user password
        - rabbitmqctl add_vhost rabbitmq.domain.lan
        - rabbitmqctl set_permissions -p rabbitmq.domain.lan password ".*" ".*" ".*"

mongodb:
    ...
    onrun:
        - mongodump --host mongo-prd.domain.lan --port 27017 --out /data/mongodb/dumps/latest
        - mongorestore -d database /data/mongodb/dumps/latest/database

Ce serait plutôt utile et résout un cas d'utilisation.

: +1:

Cela rendra l'utilisation de docker-compose plus viable pour les tests fermés dans le cadre d'un pipeline de CD

: +1:

Ceci est un duplicata de # 877, # 1341, # 468 (et quelques autres).

Je pense que la bonne façon de prendre en charge cela est le # 1510 et de permettre aux outils externes d'effectuer des opérations lorsque vous frappez l'événement que vous voulez.

Fermeture en double

Ce serait très utile. Je ne comprends pas l'argument "oh vous pourriez faire ça avec un script bash". Bien sûr, nous pourrions le faire avec un script bash. Je pourrais aussi faire tout ce que Docker-compose fait avec un script bash. Mais le fait est qu'il existe un seul fichier YAML qui contrôle votre environnement de test et qu'il peut être lancé avec une simple commande docker-compose up .

Ce n'est pas la mission de Compose de faire tout ce qui pourrait être fait avec un script shell ou Makefile - nous devons tracer une ligne quelque part pour trouver un équilibre entre l'utilité et éviter les ballonnements.

De plus, une propriété importante du fichier Compose est qu'il est assez portable sur les machines - même les machines Mac, Linux et Windows. Si nous permettons aux gens de mettre des commandes shell arbitraires dans le fichier Compose, ils deviendront beaucoup moins portables.

@aanand Pour être honnête, être capable d'exécuter un docker exec n'implique pas automatiquement une incompatibilité x-plat.

Toutes mes excuses - J'ai mal interprété ce problème car il s'agissait d'exécuter des commandes sur la machine hôte. Pourtant, mon premier point tient.

Je comprends votre point @aanand. Cela ne me semble pas hors de propos, car déjà docker-compose fait beaucoup des mêmes choses que le moteur normal docker , comme command , expose , ports , build , etc. Ajouter la fonctionnalité exec ajouterait plus de puissance à docker-compose pour en faire un véritable guichet unique pour le réglage les environnements de développement.

@aan et le principal problème pour de nombreux développeurs et pipelines CI est d'avoir une donnée très proche de l'environnement de production. Comme un vidage d'une base de données. J'ai créé ce ticket il y a 1 an et rien ne bouge dans le docker compose.

Vous suggérez donc un Makefile ou un Bashcript juste pour exécuter un exécutable https://github.com/docker/compose/issues/1809#issuecomment -128073224

Ce que je suggère à l'origine est onrun (ou oncreate) qui garde l'idempotence. Il suffit de courir au premier départ. Si le conteneur est arrêté ou mis en pause, le nouveau démarrage ne s'exécutera pas en cours d'exécution (ou en création)

Enfin, dans mon dépôt git, j'aurai un fichier de composition, un fichier docker et un fichier makefile avec gestion de l'idempotence (peut makefile pourrait créer un fichier d'état). Génie!

Il y a une grande différence entre command , expose , etc. et exec . Le premier groupe comprend les options de conteneur, exec est un point de terminaison de commande / api. C'est une fonction distincte, pas des options de la fonction de création de conteneur.

Il existe déjà plusieurs façons d'accomplir cela avec Compose (https://github.com/docker/compose/issues/1809#issuecomment-128059030). onrun existe déjà. C'est command .

Concernant le problème spécifique du vidage ou du chargement de données depuis une base de données, il s'agit plutôt de tâches de type "workflow" ou "build automation", qui sont généralement effectuées dans un Makefile. J'ai prototypé un outil pour exactement ces cas d'utilisation appelé dobi , qui exécute toutes les tâches dans des conteneurs. Il s'intègre également très bien avec Compose. Vous pourriez être intéressé à l'essayer si vous n'êtes pas satisfait de Makefiles. Je travaille sur un exemple de cas d'utilisation d'initialisation / chargement de base de données.

@dnephin onrun n'est pas un simple command parce que vous manquez simplement l'idempotence.

Imaginons. create lors de la création du conteneur et ne sera plus jamais exécuté (vidage et restauration).

exec:
    create:
        - echo baby
    destroy:
        - echo keny
    start:
        - echo start
    stop:
        - echo bye

Si vous avez besoin de plus d'exemples:

Merci pour dobi, mais si vous avez besoin de créer un outil pour améliorer la composition, la composition est mauvaise et il vaut mieux utiliser un outil plus puissant.

mais si vous avez besoin de créer un outil pour améliorer la composition, la composition est mauvaise et il vaut mieux utiliser un outil plus puissant.

C'est comme dire "si vous avez besoin d'applications pour améliorer votre système d'exploitation, votre système d'exploitation est mauvais". Aucun outil ne devrait tout faire. La philosophie Unix est de faire une chose et de bien la faire . C'est ce que nous faisons ici. Compose fait sa seule chose "orchestrer les conteneurs pour exécuter une application". Ce n'est pas un outil d'automatisation de construction.

C'est comme dire "si vous avez besoin d'applications pour améliorer votre système d'exploitation, votre système d'exploitation est mauvais". Aucun outil ne devrait tout faire. La philosophie Unix est de faire une chose et de bien la faire. C'est ce que nous faisons ici.

Wow je pense que nous avons atteint la meilleure mauvaise foi.

Malheureusement, un simple composant réutilisable n'est pas la façon dont les choses se passent. Docker crée maintenant des outils pour lancer des serveurs cloud, des systèmes de clustering et un large éventail de fonctions: création d'images, exécution d'images, téléchargement, téléchargement et éventuellement superposition de réseaux, le tout compilé dans un binaire monolithique fonctionnant principalement en tant que root sur votre serveur . Le manifeste du conteneur standard a été supprimé. Nous devrions arrêter de parler des conteneurs Docker et commencer à parler de la plate-forme Docker. Cela ne devient pas le simple bloc de construction composable que nous avions envisagé.

Vous pouvez donc garantir que nous ne verrons jamais «docker compose» écrit dans Go inside dans le binaire monolithique de docker pour garder la philosophie unix? https://www.orchardup.com/blog/orchard-is-joining-docker

Pour continuer vers cet objectif initial, nous rejoignons Docker. Entre autres choses, nous allons continuer à travailler pour faire de Docker la meilleure expérience de développement que vous ayez jamais vue - à la fois avec Fig et en incorporant les meilleures parties de Fig dans Docker lui-même.

Donc, en bref, il n'y a aucun moyen de faire des choses comme charger des appareils avec compose ..? Je dois dire que je suis surpris ...
Le moyen officiel est d'ajouter le chargement des appareils à mon conteneur de production? Ou pour écrire un script shell autour de mon fichier de composition? Dans le dernier cas, je pourrais aussi simplement exécuter «docker run» comme je l'ai fait auparavant.

@discordianfish , Si, d'une manière ou d'une autre, quelqu'un se réveillait sur le fait que les ingénieurs CI / CD doivent être capables de gérer les événements du cycle de vie et l'orchestration au moins à un niveau très basique, alors qui sait docker / docker-compose peut en fait faire son sortir des pipelines de développement local et des infrastructures de test et trouver une place dans plus d'environnements de production. J'espère que quiconque travaille sur les piles résoudra ces problèmes, mais je ne retiendrai pas mon souffle.

Après tout, ce qui doit être fait au moment de la construction peut être différent de ce qui est nécessaire au moment de l'exécution, et ce qui est nécessaire au moment de l'exécution varie souvent selon l'environnement de déploiement ...

C'est un peu un travail ennuyeux de faire savoir à mes scripts externes si un up va créer ou démarrer des conteneurs ...

Et ce sont des choses avec lesquelles certains hooks de cycle de vie + commandes + variables d'environnement pourraient aider.

Vous le voyez dans les frameworks de gestion des services et autres outils d'orchestration ... pourquoi pas dans docker-compose?

Vous pourriez être intéressé par https://github.com/dnephin/dobi , qui est un outil sur lequel j'ai travaillé et qui a été conçu pour ces flux de travail.

@dnephin arrête de spammer ce problème avec vos outils. Nous voyons votre commentaire avant et la réponse est la même. Makefile / bash est probablement meilleur qu'un nième "my tool enhancement docker".

Merci pour votre commentaire constructif. Je n'avais pas réalisé que j'avais déjà mentionné dobi sur ce fil il y a 8 mois.

Si vous êtes satisfait de Makefile / bash, c'est génial! Je suis content que votre problème soit résolu.

Ajout d'un commentaire lié à ce sujet ici: https://github.com/docker/compose/issues/1341#issuecomment -295300246

@dnephin pour celui-ci, mon commentaire peut être appliqué:

Tellement triste que ce numéro ait été clos en raison d'une certaine réfractarité à l'évolution: déçu:

La plus grande valeur de la composition de docker est la standardisation

C'est le but. Si nous pouvions "simplement" écrire un fichier .sh ou autre chose pour faire le travail sans utiliser Docker Compose, pourquoi Docker Compose existe-t-il? :confus:

Nous pouvons comprendre que c'est un gros travail, comme @ shin- l'a dit:

c'est malheureusement trop lourd à supporter à ce stade du projet

:cœur:

Mais vous ne pouvez pas dire "Faites un script" ce qui signifie "Hé, c'est trop dur, on ne va pas y arriver".

Si c'est difficile à faire, dites simplement "Votre idée est intéressante et elle répond à certains besoins, mais c'est vraiment difficile à faire et nous n'avons pas les ressources pour le faire pour le moment ... Peut-être pourriez-vous la développer et demander une demande de tirage "ou quelque chose comme ça: ampoule:

Dans # 1341, je ne vois "que" un moyen d'écrire dans docker-compose.yml commandes comme nmp install qui seraient exécutées avant ou après certains événements (comme la création de conteneurs), comme vous le feriez avec docker exec <container id> npm install par exemple.

Cas d'utilisation

J'ai une image NodeJS personnalisée et je veux exécuter npm install dans le conteneur créé à partir de celle-ci, avec un docker-compose up --build .

Mon problème est: le code de l'application n'est pas ajouté dans le conteneur, il est monté dedans avec un volume, défini dans docker-compose.yml :

custom-node:
    build: ../my_app-node/
    tty: true
    #command: bash -c "npm install && node"
    volumes:
     - /var/www/my_app:/usr/share/nginx/html/my_app

donc je ne peux pas exécuter npm install dans le Dockerfile car il a besoin du code d'application pour vérifier les dépendances. J'ai décrit le comportement ici: http://stackoverflow.com/questions/43498098/what-is-the-order-of-events-in-docker-compose

Pour exécuter npm install , je dois utiliser une solution de contournement, l'instruction command :

command: bash -c "npm install && node"

ce qui n'est pas vraiment propre: déçu: et que je ne peux pas exécuter sur les versions Alpine (ils n'ont pas installé Bash).

Je pensais que Docker Compose fournirait un moyen d'exécuter des commandes exécutables sur des conteneurs, par exemple:

custom-node:
    build: ../my_app-node/
    tty: true
    command: node
    volumes:
     - /var/www/my_app:/usr/share/nginx/html/my_app
    exec:
     - npm install

Mais ce n'est pas le cas, et je pense qu'il manque vraiment!

Je m'attendais à ce que compose soit conçu pour les tests, mais je me trompe probablement et il est davantage destiné au développement local, etc. J'ai rencontré plusieurs autres aspérités comme des conteneurs orphelins et la relation peu claire entre le nom du projet, le chemin et la façon dont il est utilisé pour identifier la propriété, que se passe-t-il si vous avez plusieurs fichiers de composition dans le même répertoire, etc. Donc, dans l'ensemble, cela ne semble pas être un bon choix pour CI.
Au lieu de cela, je prévois de réutiliser mes manifestes de production k8s dans CI en exécutant kubelet de manière autonome. Cela nécessitera également beaucoup de colle, mais au moins de cette façon, je peux utiliser les mêmes déclarations pour dev, test et prod.

@ lucile-sticky vous pouvez utiliser sh -c en alpin.

Cela ressemble à ce que vous voulez, c'est "construire l'automatisation" qui n'est pas le rôle de docker-compose. Avez-vous regardé dobi ?

Deux questions:

  • Pourquoi ce n'est pas le rôle de Docker Compose?
  • Si le but est de n'avoir qu'un seul outil pour les gérer tous, pourquoi utiliser un autre outil pour effectuer une tâche que Docker Compose n'est pas capable de faire?

Cette fonctionnalité est très nécessaire!

@ lucile-collant

Pourquoi ce n'est pas le rôle de Docker Compose?

Parce que le rôle de Compose est clairement défini et n'inclut pas ces fonctions.

Compose est un outil permettant de définir et d'exécuter des applications Docker multi-conteneurs. Avec Compose, vous utilisez un fichier Compose pour configurer les services de votre application. Ensuite, à l'aide d'une seule commande, vous créez et démarrez tous les services à partir de votre configuration

Si le but est de n'avoir qu'un seul outil pour les gérer tous, pourquoi utiliser un autre outil pour effectuer une tâche que Docker Compose n'est pas capable de faire?

Nous ne voulons pas être le seul outil pour les gouverner tous. Nous suivons la philosophie UNIX et croyons qu'il faut "faire en sorte que chaque programme fasse bien une chose. Pour faire un nouveau travail, reconstruisez à nouveau plutôt que de compliquer les anciens programmes en ajoutant de nouvelles fonctionnalités."
Il est normal d'être en désaccord avec cette philosophie, mais c'est ainsi que Docker développe des logiciels.

Je crée ce numéro, en août 2015, chaque année quelqu'un ajoute un commentaire et nous bouclons sur les mêmes questions avec les mêmes réponses (et c'est sûr que vous verrez @dnephin faire une annonce pour son outil).

@tibia-

Vous ne pouvez pas séparer «build» et «provision» dans les outils d'orchestration.

Par exemple, pouvez-vous en connaître un:

Lorsque vous configurez un service, vous devez le provisionner. Si je déploie un tomcat, je dois le provisionner avec une guerre, si je crée une base de données, je dois injecter des données, etc. peu importe comment le conteneur doit être démarré (laissez le responsable de l'image le gérer). Le but principal d'un "provisionner" dans le cas Compose est d'éviter tout malentendu entre "ce qui commence mon conteneur" et "quelle disposition il".

Comme dit votre citation dans le document de composition "Avec Compose, vous utilisez un fichier Compose pour configurer les services de votre application. Ensuite , à l'aide d'une seule commande, vous créez et démarrez tous les services à partir de votre configuration"

Philosophie Unix? Laissez-moi rire. Je vous renvoie à la même réponse que j'ai faite dans ce numéro https://github.com/docker/compose/issues/1809#issuecomment -237195021.
Voyons comment "moby" va évoluer dans la philosophie Unix.

@ shin- docker-compose n'adhère pas à la philosophie Unix par un effort d'imagination. Si docker-compose adhérait à la philosophie Unix, il y aurait des commandes discrètes pour chacun des éléments build, up, rm, start, stop, etc. et ils auraient chacun un stdin, stdout et stderr utilisables qui se comportaient de manière cohérente. dit l'administrateur système unix avec plus de 20 ans d'expérience, notamment System V, HP-UX, AIX, Solaris et Linux

Revenons à l'aperçu pour composer

Compose est un outil permettant de définir et d'exécuter des applications Docker multi-conteneurs. Avec Compose, vous utilisez un fichier Compose pour configurer les services de votre application. Ensuite, à l'aide d'une seule commande, vous créez et démarrez tous les services à partir de votre configuration.

Enfin, docker-compose est un outil d'orchestration pour gérer un groupe de services basé sur des conteneurs créés à partir d'images docker. Ses principales fonctions sont de «créer», «démarrer», «arrêter», «mettre à l'échelle» et «supprimer» les services définis dans un fichier docker-compose.yml.

De nombreux services nécessitent l'exécution de commandes supplémentaires au cours de chacune de ces transitions du cycle de vie. la mise à l'échelle des clusters de bases de données nécessite souvent de rejoindre ou de supprimer des membres d'un cluster. la mise à l'échelle des applications Web nécessite souvent de notifier à un équilibreur de charge que vous avez ajouté ou supprimé un membre. certains administrateurs système paranoïaques aiment vider de force leurs journaux de base de données et créer des points de contrôle lors de l'arrêt de leurs bases de données.

La plupart des outils d'orchestration nécessitent une action sur la transition d'état. Vous le trouverez dans les outils AWS, les outils de Google, le contremaître, le chef, etc. la plupart des choses qui vivent dans cet espace d'orchestration ont une sorte de crochet de cycle de vie.

Je pense que cela est fermement du ressort de docker-compose étant donné qu'il s'agit d'un outil d'orchestration et qu'il est conscient des changements d'état. Je ne pense pas que les événements ou les scripts externes correspondent au cas d'utilisation. Ils ne sont pas idempotents, il est beaucoup plus difficile de lancer un «deuxième» service à côté de composer pour suivre les événements. Le fait que les hooks s'exécutent à l'intérieur du conteneur ou à l'extérieur du conteneur est un détail d'implémentation.

À la fin de la journée, il y a un réel besoin qui est exprimé par les utilisateurs de docker-compose et @aanand , @dnephin , @ shin- semblent le rejeter. Ce serait bien de voir cela inclus sur une feuille de route.

Ce type de fonctionnalité bloque actuellement mon adoption de docker dans mes déploiements de test et de production en production. J'aimerais vraiment que cette question soit traitée d'une manière ou d'une autre plutôt que rejetée.

Je pense que ce sera très utile!

Pour moi, le problème est que lorsqu'un conteneur d'application A exécute le service 'a' dépendant du conteneur B de base de données exécutant le service b. Ensuite, un conteneur échoue à moins que son b ne soit configuré.
Je préférerais utiliser des images Docker Hub au lieu de réécrire mes propres Dockerfiles. Mais cela signifie que A échoue et qu'aucun conteneur n'est créé. La seule option est de

  1. Utilisez B comme image de base et créez mon propre Dockerfile.
  2. Laissez A échouer et configurez b dans le script et redémarrez A.

J'ai exactement le même cas d'utilisation que @ lucile-sticky.

@lekhnath pour mon cas, je l'ai résolu en éditant l'option command dans mon docker-compose.yml :

command: bash -c "npm install && node"

Mais c'est tellement moche TT

@ lucile-sticky Il convient de noter que cela remplace toute commande définie dans le Dockerfile du conteneur, cependant. J'ai contourné ce problème en montant un script shell personnalisé en utilisant volumes , en faisant que le command de mon fichier Docker Compose exécute ce script, et en y incluant le CMD de Dockerfile .

Pourquoi ce problème est-il clos? _écrire un script bash_ ou _utiliser cet outil que j'ai écrit_ n'est pas une raison valable pour fermer ce problème.

C'est une fonctionnalité très utile et importante qui est requise dans de nombreux cas d'utilisation où compose est utilisé.

@dnephin Pensez-vous que l'exécution de scripts d'initialisation

Demandez à quelqu'un de regarder dobi si vous ne l'avez pas fait, veuillez le faire ici :)
image

Je suppose que rien ne s'est jamais produit avec ça. J'adorerais voir une sorte de fonctionnalité dans le fichier docker-compose où nous pourrions écrire quand une commande doit être exécutée, comme l'exemple @ ahmet2mir a donné.

Très triste de voir cette fonctionnalité ne pas être implémentée.

Implémentez cette fonctionnalité s'il vous plaît, je dois installer automatiquement les fichiers après la composition de docker, car les dossiers où le fichier doit être copié sont créés après l'initialisation des conteneurs.
Merci

Il est incroyable que cette fonctionnalité ne soit pas encore implémentée!

C'est une forme très pauvre @dnephin. Vous avez empêché la mise en œuvre d'une fonctionnalité aussi recherchée pour ce qui semble principalement une auto-promotion, et vous n'êtes même pas disposé à poursuivre la conversation.

Je suis désolé, je ne pouvais pas penser à un langage plus doux pour le dire, l'absence de cette fonctionnalité a ajouté une fraction à notre flux de travail, comme beaucoup d'autres développeurs et équipes, et vous avez été un obstacle à la résolution de ce problème.

Oh, faisons alors le unix-way .
_Just_ (multiplexer alors) diriger docker-compose up stdin vers chaque conteneur ' CMD ?
Pour qu'un tel fichier yaml

services:
  node:
    command: sh -

ferait ce travail: cat provision.sh | docker-compose up
conteneurs sont des choses exec UTING, je ne vois pas une meilleure utilisation des stdin que les commandes en passant le long.

Une alternative pourrait être:

services:
  node:
    localscript: provision.sh

Bien qu'un peu centré sur le shell, cela résoudrait 99% des cas d'utilisation de provisionnement.

Même s'il existe des cas d'utilisation valables et de nombreuses votes favorables à ce sujet ... cela a toujours été refusé. Dommage car moi, comme beaucoup d'autres ici, je trouverais cela extrêmement utile.

Ajout de mon +1 à la grande pile de + existants

... un autre +1 ici!

Je pense que s'il y a une telle demande pour cette fonctionnalité, elle devrait être mise en œuvre, des outils sont là pour nous aider à atteindre nos objectifs et nous devrions les modeler pour nous aider à ne pas nous rendre la vie plus difficile.
Je comprends la philosophie à laquelle quelqu'un adhère, mais l'ajout d'une sorte de "commandes hooks" ne devrait pas être un problème.

+1 +1

En attendant cette fonctionnalité, j'utilise le script suivant pour effectuer une tâche similaire:

docker-start.sh

#!/usr/bin/env bash

set -e
set -x

docker-compose up -d
sleep 5

# #Fix1: Fix "iptable service restart" error

echo 'Fix "iptable service restart" error'
echo 'https://github.com/moby/moby/issues/16137#issuecomment-160505686'

for container_id in $(docker ps --filter='ancestor=reduardo7/my-image' -q)
  do
    docker exec $container_id sh -c 'iptables-save > /etc/sysconfig/iptables'
  done

# End #Fix1

echo Done

@ reduardo7 Alors vous pourriez aussi bien supprimer docker-compose complètement, de cette façon avoir une dépendance en moins.

@omeid , vous avez raison! C'est une solution de contournement pour effectuer une tâche similaire, désolé!

@ reduardo7 Pas besoin de vous excuser, ce que vous avez publié sera probablement utile à certaines personnes.
Je faisais juste remarquer que le problème initial est toujours d'actualité et n'aurait pas dû être fermé. :)

Je comprends les stands de

Cependant, si de tels modèles sont fréquemment utilisés, que diriez-vous de présenter un guide (ou un test) afin que d'autres puissent l'utiliser facilement?

Il ne semble pas y avoir de désaccord sur le fait que ce modèle peut être utilisé fréquemment.

@MaybeS Le seul désaccord est que @dnephin préfère voir son outil dopey promu au lieu d'aider à faire de docker-composer un meilleur produit.

@omeid oui en effet.

exemple d'aujourd'hui de vouloir un moyen pour composer de faire une forme de onrun

version: "3.3"
services:
  gitlab:
    image: 'gitlab/gitlab-ce:latest'
    restart: always
    hostname: 'gitlab'
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        # NOTE: this URL needs to be right both for users, and for the runner to be able to resolve :() - as its the repo URL that is used for the ci-job, and the pull url for users.
        external_url 'http://gitlab:9090'
        gitlab_rails['gitlab_shell_ssh_port'] = 2224
    ports:
      - '9090:9090'
      - '2224:22'
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock

et bien sûr, le coureur n'est pas inscrit - et pour ce faire, nous devons

  1. extraire le jeton de la base de données dans gitlab
  2. run register dans le conteneur runner

donc au lieu de définir le déploiement de mon application multi-conteneurs dans simplement docker-compose, je dois utiliser des moyens secondaires - dans ce cas ... docs?

export GL_TOKEN=$(docker-compose exec -u gitlab-psql gitlab sh -c 'psql -h /var/opt/gitlab/postgresql/ -d gitlabhq_production -t -A -c "SELECT runners_registration_token FROM application_settings ORDER BY id DESC LIMIT 1"')
docker-compose exec gitlab-runner gitlab-runner register -n \
  --url http://gitlab:9090/ \
  --registration-token ${GL_TOKEN} \
  --executor docker \
  --description "Docker Runner" \
  --docker-image "docker:latest" \
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock \
  --docker-network-mode  "network-based-on-dirname-ew_default"

mmm, je pourrais peut-être pirater quelque chose, dans lequel j'ai un autre conteneur qui a le socket docker, et docker exec's

que parier il y a un moyen ...

par exemple, je peux ajouter:

  gitlab-initializer:
    image: docker/compose:1.18.0
    restart: "no"
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./gitlab-compose.yml:/docker-compose.yml
    entrypoint: bash
    command: -c "sleep 200 && export GL_TOKEN=$(docker-compose -p sima-austral-deployment exec -T -u gitlab-psql gitlab sh -c 'psql -h /var/opt/gitlab/postgresql/ -d gitlabhq_production -t -A -c \"SELECT runners_registration_token FROM application_settings ORDER BY id DESC LIMIT 1\"') && docker-compose exec gitlab-runner gitlab-runner register -n --url http://gitlab:9090/ --registration-token ${GL_TOKEN} --executor docker --description \"Docker Runner\" --docker-image \"docker:latest\" --docker-volumes /var/run/docker.sock:/var/run/docker.sock --docker-network-mode  \"simaaustraldeployment_default\""

dans mon fichier de composition - même si j'ai besoin d'une sorte de boucle / attente, car gitlab n'est pas prêt tout de suite - sleep 200 pourrait ne pas suffire.

donc - vous __pouvez__ pirater une sorte de modèle comme celui-ci directement dans un docker-compose.yml - mais personnellement, je préfère de loin un support plus propre que celui-ci :)

@SvenDowideit onrun existe déjà, c'est entrypoint ou cmd .

Le script de point d'entrée pour cette image fournit même un crochet pour vous. $GITLAB_POST_RECONFIGURE_SCRIPT peut être défini sur le chemin d'un script qu'il exécutera une fois la configuration terminée (voir /assets/wrapper dans l'image). Définissez la variable env sur le chemin de votre script qui enregistre psql + et vous êtes prêt.

Même si l'image n'a pas fourni ce crochet, c'est quelque chose qui peut être ajouté assez facilement en étendant l'image.

bien que j'aie besoin d'une sorte de boucle / attente, car gitlab n'est pas prêt tout de suite - sleep 200 pourrait ne pas suffire.

Cela serait nécessaire même avec une option "exec-after-start". Étant donné que le script de point d'entrée fournit en fait un crochet, je pense que ce n'est probablement pas nécessaire avec cette solution.

non, je (pense) que vous avez manqué une partie du problème que je montre:

dans mon cas, j'ai besoin d'accéder aux deux conteneurs, pas seulement à un seul - donc entrypoint / command ne me donne _pas_ cela.

GL_TOKEN provient du conteneur gitlab, et est ensuite utilisé dans le conteneur gitlab-runner pour s'enregistrer.

donc le hack que je fais, utilise l'image docker/compose pour ajouter un troisième conteneur - ce n'est pas quelque chose pour lequel vous pouvez modifier la configuration / le point d'entrée / les paramètres d'un conteneur, et c'est entièrement un exemple (trivial) d'un coordination multi-conteneurs qui a besoin de plus.

J'ai travaillé sur des choses pour les rendre un peu plus magiques - ce qui signifie essentiellement que mon conteneur d'initialisation a des boucles de sommeil, car il faut un certain temps à gitlab pour s'initialiser.

TBH, je commence à penser que l'utilisation d'un script, s'exécutant dans un conteneur d'initialisation qui utilise le fichier de composition lui-même et l'image docker / compose, _est_ la bonne façon de masquer ce genre de complexité - pour la non-production "essayez moi, et ça marchera juste "des situations comme ça.

_IF_ je devais envisager un sucre syntaxique étrange pour aider, peut-être que j'irais pour quelque chose comme:

gitlab-initializer:
    image: docker/compose:1.18.0
    restart: "no"
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./gitlab-compose.yml:/docker-compose.yml
    entrypoint: ['/bin/sh']
    command: ['/init-gitlab.sh']
    file:
      path: /init-gitlab.sh
      content: |
            for i in $(seq 1 10); do
                export GL_TOKEN=$(docker-compose -f gitlab-compose.yml -p sima-austral-deployment exec -T -u gitlab-psql gitlab sh -c 'psql -h /var/opt/gitlab/postgresql/ -d gitlabhq_production -t -A -c "SELECT runners_registration_token FROM application_settings ORDER BY id DESC LIMIT 1"')
                echo "$i: token($?) == $GL_TOKEN"
                ERR=$?

                if [[ "${#GL_TOKEN}" == "20" ]]; then
                    break
                fi
                sleep 10
            done
            echo "GOT IT: token($ERR) == $GL_TOKEN"

            for i in $(seq 1 10); do
                if  docker-compose -f gitlab-compose.yml  -p sima-austral-deployment exec -T gitlab-runner \
                    gitlab-runner register -n \
                    --url http://gitlab:9090/ \
                    --registration-token ${GL_TOKEN} \
                    --executor docker \
                    --description "Docker Runner" \
                    --docker-image "docker:latest" \
                    --docker-volumes '/var/run/docker.sock:/var/run/docker.sock' \
                    --docker-network-mode  "simaaustraldeployment_default" ; then
                        echo "YAY"
                        break
                fi
                sleep 10
            done

c'est-à-dire, comme cloud-init: http://cloudinit.readthedocs.io/en/latest/topics/examples.html#writing -out-arbitrary-files

mais en fin de compte, nous _ avons_ une solution pour coordonner des choses complexes à plusieurs conteneurs depuis l'intérieur d'un docker-compose-yml.

Si vous êtes en mesure de définir un jeton prédéfini, vous pouvez le faire à partir d'un script de point d'entrée dans gitlab-runner . N'y a-t-il aucun moyen de définir cette heure?

@dnephin Au moment où vous parlez de script, vous êtes hors de propos d'une année-lumière et plus encore.

onrun n'est pas la même chose que entrypoint ou cmd .

Le entrypoint / cmd sert à configurer l'exécutable qui s'exécutera en tant que conteneurs init / PID 1.

L'idée mentionnée dans ce problème et dans de nombreux autres est d'environ init scripts , ce qui est différent de init dans le contexte du démarrage, et concerne les scripts d'initialisation d'application, pensez à la configuration de la base de données.

@dnephin, il serait probablement plus utile de vous concentrer sur l'ensemble de problèmes général, plutôt que d'essayer de contourner les problèmes d'un ensemble de conteneurs spécifique.

D'après ce que j'ai vu, non, c'est un secret généré - mais en réalité, ce n'est pas la seule exigence de coordination multi-conteneurs que même ce petit système de jeu est susceptible d'avoir - c'est juste le plus rapide pour moi. prototype en public.

Comment est-il possible que nous ayons pu remplacer entrypoint et command dans un fichier de composition depuis la v1 (https://docs.docker.com/compose/compose-file/compose-file -v1 / # entrypoint) et n'avez toujours pas de directive telle que onrun pour exécuter une commande lorsque les conteneurs sont en place?

TBH, je ne pense pas vraiment que onrun soit plausible - Docker, ou l'orchestrateur ne sait pas ce que signifie "les conteneurs sont tous en place" - dans l'un de mes cas, le HEALTHCHECK échouera, jusqu'à ce que je le fasse des "trucs" supplémentaires où j'obtiens des informations d'un conteneur, et l'utilise pour lancer d'autres choses dans d'autres conteneurs.

Et _si_ j'ai raison, cela signifie que j'ai essentiellement besoin d'un conteneur Operator, qui contient du code qui détecte quand certaines parties du système multi-conteneurs sont suffisamment prêtes pour qu'il fasse une partie du travail, (rinçage et répétition), jusqu'à il a terminé son travail et sort, ou peut-être même surveille les choses et les corrige.

Et cela me semble être un travail qui est mieux résolu (dans docker-compose) par un conteneur docker-compose avec du code.

Je vais probablement jouer avec la façon de convertir ensuite cet opérateur en quelque chose qui peut gérer les piles d'essaim de docker (en raison d'autres besoins du projet).

Je ne suis pas tout à fait sûr qu'il y ait beaucoup de sucre syntaxique qui pourrait être ajouté à docker-compose, à moins que ce soit quelque chose comme marquer un conteneur comme "ceci est un opérateur, donnez-lui des capacités magiques".

On voit clairement que les développeurs ne veulent pas écouter les utilisateurs .. Je vais regarder un autre outil ... docker-compose est un gros problème .. Je ne comprends pas pourquoi vous ne pouvez pas comprendre que la seule chose utile qui vient de docker-composer est un outil de construction ... J'ai passé beaucoup de temps à chercher COMMENT exécuter une commande SIMPLE pour ajouter des autorisations à l'intérieur d'un conteneur à l'utilisateur actif.

Il semble que docker-composer ait simplement l'état NOT DONE ...

Moi aussi je veux quelque chose qui va onrun dans mon fichier de composition

__BUT__, ni les conteneurs, ni la composition n'ont un moyen de savoir ce que signifie onrun . C'est pourquoi le modèle d'opérateur existe et pourquoi j'ai créé les exemples sur https://github.com/docker/compose/issues/1809#issuecomment -362126930

il __est__ possible de le faire aujourd'hui - en substance, vous ajoutez un service onrun qui attend que tous les autres services soient réellement prêts à interagir (dans le cas de gitlab, cela prend un peu de temps), puis faites tout ce que vous devez faire pour coordonner les choses.

S'il y a quelque chose qui ne fonctionne pas avec cela, veuillez nous le dire, et nous verrons si nous pouvons trouver quelque chose!

Je veux aussi quelque chose qui sera exécuté dans mon fichier de composition

MAIS, ni les conteneurs, ni la composition n'ont un moyen de savoir ce que signifie onrun.

Comme je le vois, onrun par service, signifie quand le premier processus de conteneur démarre. Dans un plus grand nombre de cas, le conteneur n'exécute de toute façon qu'un seul processus, car c'est la méthode recommandée pour exécuter les conteneurs.

Le problème du support multiplateforme a été résolu plus tôt, car la commande peut être complètement indépendante du système d'exploitation via docker exec , de la même manière que RUN ne doit pas nécessairement signifier une commande linux dans Dockerfile.
https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-docker/manage-windows-dockerfile

En attente de la fonctionnalité onrun

J'ai aussi besoin de ces fonctionnalités onrun , je pensais que c'était dans cet outil. En raison de cette fonctionnalité manquante, je dois maintenant maintenir 2 scripts man.

Les gars, que faire si je crée un wrapper autour de cette docker-compose et autorise cette fonctionnalité onrun ? Souhaitez-vous l'utiliser?

@wongjiahau peut être quelque chose comme ça? https://github.com/docker/compose/issues/1809#issuecomment -348497289

@ reduardo7 Oui, j'ai pensé à l'envelopper dans un script appelé docker-composei , et avec le docker-composei.yml qui contient l'attribut onrun .
Btw, docker-composei signifie docker-compose improved .

La vraie solution est probablement de construire une image 'Orchestrator' qui exécute et gère (via des scripts bash) les 'App Images' (éventuellement en utilisant docker) en interne. Sinon, nous demanderons toujours plus de fonctionnalités pour un outil qui "n'est pas destiné à faire ce que nous voulons qu'il fasse".

Nous devrions donc même envisager Docker dans Docker ...

juste pour ajouter mon soutien pour cette fonctionnalité proposée. onrun a du sens, mais pour élargir un peu l'utilité potentielle et la prouver pour l'avenir, peut-être que quelqu'un a besoin de regarder une architecture «onevent» plus large, dont l'une serait onrun.

Étant donné la direction dominante pour que les conteneurs soient autonomes, un service par conteneur, le conteneur doit être autonome en termes de connaissance du contexte opérationnel. Ce qui en découle, le fichier de composition doit être le moyen de définir cela, et non des scripts boulonnés. Difficile de contester cela, à moins que vous ne soyez un fanatique égocentrique.

Dans mon cas, mes conteneurs redis chargent des scripts lua après le démarrage du serveur redis. Dans un environnement normal sans conteneur, je demande à systemd d'exécuter un script post-démarrage. Simple et cohérent avec l'architecture systemd. Un principe similaire devrait exister pour compose étant donné son rôle dans la configuration du contexte pour l'exécution des conteneurs.

En guise de conseil général aux responsables de la maintenance, veuillez vous concentrer sur des principes de fonctionnement éprouvés et non sur des préférences personnelles.

donc la solution (après avoir lu tout ce fil de discussion) est d'utiliser un script bash pour faire le travail ... dans ce cas, je supprimerai docker-compose (nous pouvons tout faire avec le docker cmd ...)

thx dev pour écouter les gens qui utilisent vos choses :)

En voyant la quantité de messages contenant des arguments et des contre-arguments combattant des propositions simples (comme avoir un événement onrun ), ma première impression honnête est que Github Issues est devenu un endroit où les _owners_ (développeurs de projets) présentent leur ego et leur intelligence en utilisant leurs connaissances et leur argument technique pour s'opposer à la contribution intelligente des utilisateurs.

S'il vous plaît, rendons l'Open Source vraiment _open_.

des mises à jour sur cette fonctionnalité? quel est le problème?

@ v0lume Je suppose que vous n'avez pas pris la peine de lire les réponses tout au long de cet article

Il ne semble toujours pas y avoir de solution ... Je voudrais cependant partager une solution de contournement hacky.
En spécifiant la version "2.1" dans le fichier docker-compose.yml, vous pouvez abuser du test de contrôle de santé pour exécuter du code supplémentaire à l'intérieur de l'image lorsqu'elle est démarrée. Voici un exemple:

version: '2.1'
services:
    elasticsearch:
        image: docker.elastic.co/elasticsearch/elasticsearch:5.4.3
        healthcheck:
            test: |
                curl -X PUT elasticsearch:9200/scheduled_actions -H "ContentType: application/json" -d '{"settings":{"index":{"number_of_shards":'1',"number_of_replicas":'0'}}}' &&
                curl --silent --fail localhost:9200/_cat/health ||
                exit 1
            interval: 11s 
            timeout: 10s 
            retries: 3
        environment:
            - discovery.type=single-node
            - ES_JAVA_OPTS=-Xms1g -Xmx1g
            - xpack.security.enabled=false
    main:
        image: alpine
        depends_on:
            elasticsearch:
                condition: service_healthy

Si le script healthcheck-test que vous écrivez se termine avec le code> = 1, il peut être exécuté plusieurs fois.
Le contrôle de santé d'un service ne sera exécuté que si un autre service en dépend et spécifie la condition service_healthy comme indiqué dans l'exemple.

J'aime l'approche @ T-vK et je l'ai déjà utilisée avec succès. Mais j'aimerais partager un autre ... hack:

# Run Docker container here

until echo | nc --send-only 127.0.0.1 <PORT_EXPOSED_BY_DOCKER>; do
  echo "Waiting for <YOUR_DOCKER> to start..."
  sleep 1
done

# Do your docker exec stuff here

+1
Je suis tout à fait d'accord sur ce point car la fonctionnalité est nécessaire et elle est déjà implémentée par d'autres orchestrateurs de docker comme kubernetes. Il a déjà des hooks de cycle de vie pour les conteneurs et est documenté ici .

Mais permettez-moi de contribuer à un cas d'utilisation que vous ne pouvez pas résoudre avec Dockerfiles.

Supposons que vous deviez monter un volume au moment de l'exécution et créer un lien symbolique de votre conteneur vers le volume sans connaître au préalable le nom exact du répertoire. J'ai eu un cas où le nom du répertoire était dynamique en fonction de l'environnement sur lequel je déployais et je le transmettais en tant que variable.

Bien sûr, j'ai trouvé une solution de contournement pour résoudre ce problème et il y en a plus d'un. D'un autre côté, les hooks me donneraient la flexibilité et une meilleure approche pour apporter des modifications dynamiquement sans l'envie de pirater les choses et de remplacer le Dockerfile.

Je suis content d'avoir trouvé ce problème. Je joue avec Docker et Docker compose depuis quelques années. J'espérais sérieusement l'utiliser comme un outil pour commencer à faire évoluer un système. Je reviendrai tous les ans ou deux, mais en fonction de l'attitude des responsables du projet, j'obtiendrai simplement en utilisant soit des scripts, soit un autre outil. Heureux de ne pas avoir investi beaucoup de temps et d'avoir découvert celui-ci très tôt.

Conseil de pro: Si quelqu'un qui commence tout juste à déplacer son flux de travail vers ce type d'outil a déjà besoin de ce qui est décrit ici, il pourrait être utile de repenser `` pourquoi '' vous construisez cela. Oui, vous réussissez, mais c'est parce que les gens ont utilisé la chose en premier lieu, et vous étiez probablement très ouvert à leur donner ce dont ils avaient besoin.

Bonne chance.

Je suis capable de vous donner ce que vous voulez (sauf ma petite amie) si cette fonctionnalité est mise en œuvre et je serai la personne la plus heureuse de tout l'univers :)

juste pour ajouter mon soutien pour cette fonctionnalité proposée. onrun a du sens, mais pour élargir un peu l'utilité potentielle et la prouver pour l'avenir, peut-être que quelqu'un a besoin de regarder une architecture «onevent» plus large, dont l'une serait onrun.

Ce serait bien.

Pour ajouter à cela, étant donné ce qui suit:

services:
    web:
        image: node:8-alpine
        depends_on:
            - db
    db:
        image: postgres:alpine
        onrun: "echo hi"

serait-il trop compliqué d'ajouter des scripts inter-événements?

    web:
        events:
            db_onrun: "connectAndMigrate.sh"

À mon avis, ajouter ceci à docker-compose est simple, non seulement vous, qui utilisez composer un fichier et composer stack, mais également d'autres développeurs de votre équipe.

  • En utilisant des conteneurs séparés - tout le monde doit savoir qu'il doit les exécuter.
  • Écrivez Dockerfile personnalisé - nous avons environ 20 services et pour chaque service, je devrais remplacer Dockerfile pour exécuter une commande.

Nous devons installer et configurer mkcert , par exemple, sur chaque environnement pour avoir des certificats de confiance. Il ne fait pas partie du conteneur ou du Dockerfile car il n'est pas nécessaire sur scène / production. Quelle est la bonne approche ici pour installer l'outil et tous ceux qui utilisent le fichier de composition n'ont même aucune idée de ce qui se passe dans les coulisses?

Ajout d'un autre cas d'utilisation:

Besoin d'une instance wordpress. J'ai écrit mon docker-compose.yaml. docker-compose up - Oups! Besoin de définir les autorisations de fichier du répertoire des plugins ... Je ne trouve pas d'autre moyen de le faire fonctionner, je dois définir les autorisations après l'exécution du conteneur car je lie certains fichiers de l'hôte et cela semble être le seul moyen pour corriger les permissions fs, c'est en faisant chown -Rf www-data.www-data /var/www/wp-content depuis l'intérieur du conteneur. Ecrire mon propre Dockerfile et construire, juste pour ça? Cela me semble stupide.

Heureusement pour moi, le hack healthcheck fourni ci-dessus m'a permis de l'implémenter. Je vois d'autres pages sur le Web parler du problème des autorisations de paramètres sur les volumes docker, mais les solutions suggérées n'ont pas fonctionné.

Heureux de voir que ces gardiens, @dnephin , @aanand , @
01) sshishov
02) fescobar
03) sandor11
04) Web-ted
05) v0lume
06) Webpolis
07) Skull0ne
08) usergoodvery
09) wongjiahau
10) MFQ
11) Yosefrow
12) bagermen
13) daqSam
14) Omeid
15) Dantebarba
16) Willyyang
17) SharpEdgeMarshall
18) transporteur perdu
19) fantôme
20) rodrigorodriguescosta
21) Eviter les données
22) Dextermb
23) lekhnath
24) lucile-collant
25) rav84
26) Dopry
27) ahmet2mir
28) montera82
29) poisson discordien
30) jasonrhaas
31) fferraris
32) hypergig
33) au soleil
34) sthulb

Et le nombre qui a dit non? Un énorme 3:
01) dnephin
02) aanand
03) tibia

Hmmm ... 34 à 3 ...

@ rm-rf-etc bonnes analyses ... Je ne pense même pas que @dnephin ou @aanand travaillent plus sur docker-compose. Avec de la chance, Docker prévoit de déprécier la composition au profit des piles et il ne restera plus d'équipe ici pour se plaindre et nous recommencerons à voir les progrès du produit.

Ajout d'un autre cas d'utilisation:

Besoin d'une instance wordpress. J'ai écrit mon docker-compose.yaml. docker-compose up - Oups! Besoin de définir les autorisations de fichier du répertoire des plugins ... Je ne trouve pas d'autre moyen de le faire fonctionner, je dois définir les autorisations après l'exécution du conteneur car je lie certains fichiers de l'hôte et cela semble être le seul moyen pour corriger les permissions fs, c'est en faisant chown -Rf www-data.www-data /var/www/wp-content depuis l'intérieur du conteneur.

Dans ce cas, vous pouvez également définir la propriété user dans votre fichier Compose

Ecrire mon propre Dockerfile et construire, juste pour ça? Cela me semble stupide.

On dirait que vous avez formé une opinion forte; mais de façon réaliste, il n'y aurait rien de "stupide" à écrire un Dockerfile pour modifier une image de base en fonction de vos besoins. C'est l'intention originale de toutes les images de base.

Heureusement pour moi, le hack healthcheck fourni ci-dessus m'a permis de l'implémenter. Je vois d'autres pages sur le Web parler du problème des autorisations de paramètres sur les volumes docker, mais les solutions suggérées n'ont pas fonctionné.

Heureux de voir que ces gardiens, @dnephin , @aanand , @

Ouais, bon pote d'attitude. :RÉ


@ rm-rf-etc bonnes analyses ... Je ne pense même pas que @dnephin ou @aanand travaillent plus sur docker-compose.

Ouais, cela fait maintenant quelques années - pas besoin de continuer à leur envoyer un ping sur de vieux problèmes.

Avec de la chance, Docker prévoit de déprécier la composition au profit des piles et il ne restera plus d'équipe ici pour se plaindre et nous recommencerons à voir les progrès du produit.

🙄

@ shin- mais vous venez de lui envoyer un ping avec cette réponse

J'ai récemment rencontré ce problème à nouveau et même si cela peut être fait comme indiqué dans ma solution de contournement , cela ne fonctionne que si vous spécifiez 2.1, ce qui pue imo.

C'est juste époustouflant pour moi que la position officielle semble être que vous devriez créer vos propres images de docker pour tout.
Pour moi, c'est littéralement comme dire "Si vous voulez changer un paramètre dans n'importe quel programme, vous devez modifier le code source et le recompiler.".
Chaque fois que vous ajoutez un nouveau service ou que vous souhaitez mettre à niveau vers une version plus récente de .. par exemple l'image MongoDB ou MySQL Docker, vous devez créer un nouveau Dockerfile, le construire et éventuellement le pousser dans votre registre.
C'est une énorme perte de temps et de ressources par rapport à ce que ce serait si vous pouviez simplement changer image: mongo:3.0.2 en image: mongo:3.0.3 dans votre docker-compose.yml.
Je ne suis pas en train de déclamer les longs temps de construction, je discute du fait que vous devez vous soucier de Dockerfiles et de docker build quand tout ce que vous voulez, c'est mettre à jour ou modifier un paramètre d'un service qui n'est potentiellement destiné à être utilisé comme image de base.

Et l'argument selon lequel chaque application devrait faire une chose et une seule chose pue vraiment aussi. Il ne s'agit même pas d'implémenter une fonctionnalité complètement nouvelle, mais simplement de passer un autre paramètre à docker . Cela pose également la question de savoir pourquoi docker run , docker build , docker exec , docker pull etc. font tous partie de la même application. L'argument semble un peu hypocrite maintenant, n'est-ce pas?

@ shin-, j'ai suivi votre lien et je ne vois pas en quoi la propriété user est pertinente pour définir le propriétaire d'un répertoire monté en liaison. Semble être lié aux ports.

Re: attitude: On dirait que les gens sont d'accord avec moi, alors considérez cela comme une forte rétroaction. Désolé si vous n'aimez pas la façon dont j'exprime cela, mais il semble vraiment que les demandes des utilisateurs soient ignorées, alors à quoi vous attendez-vous?

Je suis venu ici en espérant des fonctionnalités telles que le onrun: étant suggéré car je ne suis que deux jours dans l'utilisation de compose et pour moi, un outil comme celui-ci devrait avoir cette fonctionnalité.

Revenir à mes fichiers docker pour mettre à jour chacun avec un script séparé pour les fonctionnalités semble redondant. Je veux simplement injecter un jeton d'un autre conteneur dans une variable d'environnement où mon fichier dockerfile était auparavant flexible est maintenant étroitement couplé au docker-composer.yml et à la solution dans un but simple.

Merde, j'ai lu tout le fil en sautant pour trouver la réponse "ok les gars, nous avons finalement réalisé que c'est cool et nous allons l'implémenter". Triste de voir que cela n'a pas avancé.
+1 pour onrun!

@fabiomolinar , Il y a une sorte de solution, que nous utilisons beaucoup dans nos essaims de production, mais ce n'est pas aussi agréable que d'avoir un événement.

Nous utilisons l'ancre suivante

#### configure a service to run only a single instance until success
x-task: &task
  # for docker stack (not supported by compose)
  deploy:
    restart_policy:
      condition: on-failure
    replicas: 1
  # for compose (not supported by stack)
  restart: on-failure

pour répéter les tâches jusqu'à ce qu'elles réussissent. Nous créons des conteneurs pour les migrations et les tâches de configuration qui ont des résultats idempotents et les exécutons comme ceci dans notre composition locale et dans nos piles.

Le service qui dépend de la tâche doit échouer quelque peu correctement si le travail de configuration n'est pas terminé. Dans la plupart des cas, tant que vous êtes d'accord avec quelques erreurs qui frappent les utilisateurs finaux, cela vous donne une cohérence éventuelle qui fonctionnera bien dans la plupart des environnements.

Cela suppose également que vos conteneurs de services peuvent fonctionner avec des états de fin de tâche avant et après. Dans des cas d'utilisation tels que les migrations de bases de données, les services dépendants devraient être capables de fonctionner avec des schémas pré et post-migration. Il faut évidemment réfléchir à la coordination du développement et du déploiement, mais c'est une réalité générale faire des mises à jour progressives des services.

@fabiomolinar , voici un exemple de la façon dont nous utilisons cette approche dans nos services de composition ...

#### configure a service to run only a single instance until success
x-task: &task
  # for docker stack (not supported by compose)
  deploy:
    restart_policy:
      condition: on-failure
    replicas: 1
  # for compose (not supported by stack)
  restart: on-failure

#### configure a service to always restart
x-service: &service
  # for docker stack (not supported by compose)
  deploy:
    restart_policy:
      condition: any
  # for compose (not supported by stack)
  restart: always

services: 
  accounts: &accounts
    <<: *service
    image: internal/django
    ports:
      - "9000"
    networks:
      - service
    environment:
      DATABASE_URL: "postgres://postgres-master:5432/accounts"
      REDIS_URL: "hiredis://redis:6379/"

  accounts-migrate:
    <<: *accounts
    <<: *task
    command: ./manage.py migrate --noinput

Merci de le signaler @dopry. Mais mon cas était un peu plus simple. J'avais besoin de faire fonctionner mon serveur et ensuite, seulement une fois qu'il était opérationnel, je devais effectuer certaines tâches de déploiement. Aujourd'hui, j'ai trouvé un moyen de le faire en effectuant une petite gestion de processus dans une seule ligne CMD . Imaginez que le serveur et les processus de déploiement soient appelés respectivement server et deploy . J'ai ensuite utilisé:

CMD set -m; server $ deploy && fg server

La ligne ci-dessus active le mode moniteur de bashes, puis il démarre le processus server en arrière-plan, puis il exécute le processus deploy et enfin il apporte le processus server processus à nouveau au premier plan pour éviter que Docker tue le conteneur.

Pendant que nous en discutons, n'importe qui a des conseils sur la façon d'exécuter une commande sur le conteneur ou l'hôte lors de l'exécution de docker-compose up ?

Je comprends que l'exécution de n'importe quelle commande sur l'hôte compromettrait les couches de sécurité, mais je voudrais juste rm un répertoire avant ou pendant le démarrage d'un conteneur. Le répertoire est accessible à la fois sur l'hôte et le conteneur. Je ne veux pas créer une image Docker personnalisée ou avoir un script qui commence par rm , puis exécute docker-compose .

Merci!

@fabiomolinar , l'approche que vous proposez enfreint quelques principes d' application à 12 facteurs . Si vous conteneurisez votre infrastructure, je vous recommande fortement d'y adhérer étroitement.

Quelques problèmes qui pourraient découler de votre approche

  1. démarrage lent du conteneur.
  2. lors de la mise à l'échelle d'un service avec le conteneur, le déploiement s'exécute une fois pour chaque instance, ce qui peut entraîner des problèmes de concurrence intéressants.
  3. plus difficile de trier les journaux de la «tâche» et du service pour la gestion et le débogage.

J'ai trouvé l'approche que je recommande contre-intuitive au début. Cela a bien fonctionné dans la pratique dans nos environnements de développement local sous des clusters docker-compose, docker swarms et mesos / marathon. Il a également fonctionné efficacement autour du manque de «onrun».

L'approche que j'ai utilisée est en effet très moche. Je l'ai utilisé pendant un certain temps juste pour faire fonctionner mon environnement de développement. Mais j'ai déjà changé cela pour utiliser des scripts de point d'entrée et la commande at pour exécuter des scripts une fois que le serveur est opérationnel. Maintenant, mon conteneur fonctionne avec le processus correct en tant que PID 1 et répond correctement à tous les signaux.

Nous en avons encore besoin. Je ne peux pas trouver un moyen, comment je pourrais exécuter mes rollups de base de données après avoir démarré avec succès le conteneur sans le faire dans un tas de Makefiles.

@ victor-perov crée un autre conteneur pour la tâche de cumul et l'exécute en tant que service séparé

Voici quelques extraits de l'un de nos projets pour montrer un service de tâche pour exécuter une migration de base de données.

x-task: &task
  # run once deploy policy for tasks
  deploy:
    restart_policy: 
      condition: none
    replicas: 1

service:
  automata-auth-migrate:
    <<: *automata-auth
    <<: *task
    # without the sleep it can't lookup the host postgres.  maybe the command is ran before the network set is complete.
    command: sleep 5 && python /code/manage.py migrate --noinput

Eh bien, c'est la quatrième année que dure cette discussion. Alors laissez-moi ajouter mon +1 à ce cas d'utilisation d'un besoin de onrun . PS: J'aurais dû acheter du pop-corn pour tout le fil.

Moi aussi, je penserais que onrun ou équivalent (post-exécution?) Est un must. Ajouter un script wrapper et faire docker exec dans le conteneur est juste ... moche.

IMO docker compose était un excellent MVP d'orchestration de conteneurs pour convaincre les gens que la gestion des conteneurs peut être facile. Peut-être que nous, la communauté, devrions le considérer comme étant en "mode maintenance" car les solutions d'orchestration prêtes pour la production (ie kubernetes) ont proliféré. Lorsque vous avez des fonctionnalités avancées telles que les dépendances de conteneurs, combinées à des fonctionnalités absentes telles que «exécuter cette chose une fois que le conteneur est en place», cela semble correspondre au récit selon lequel le rythme du développement s'est simplement stabilisé. À tout le moins, il n'est pas évident que cette fonctionnalité _doit être_ considérée comme hors de portée.

Vous ne pouvez pas tout faire facilement avec Dockerfile. Supposons que vous souhaitiez ajouter votre propre script à un conteneur.
Par exemple, prenez le conteneur mysql et essayez d'ajouter un script simple pour appeler une API en cas d'événement.
Vous pouvez le faire soit en:

  • Changer le Dockerfile de mysql et ajouter votre propre script au conteneur avant le point d'entrée. Vous ne pouvez pas ajouter un CMD dans le Dockerfile , car ce serait un argument au ENTRYPOINT .
  • Vous pouvez exécuter le conteneur, puis copier votre script dans le conteneur en cours d'exécution et l'exécuter [ docker cp , docker exec ].

C'est pourquoi je pense aussi qu'une fonctionnalité comme onrun est bénéfique car changer le Dockerfile n'est pas toujours suffisant.

Dump, pourquoi est-ce fermé? Considérez la situation, lorsque vous utilisez une image docker officielle, comme Cassandra et que vous devez charger le schéma après son démarrage ... Vous devez implémenter votre propre solution de script bash pour cela ... euh, c'est moche

@somebi ressemble à compose est fermé ...

Juste mes deux cents: j'ai atterri ici car je dois actuellement activer manuellement les modules Apache à chaque fois que je lance le conteneur (SSL n'est pas activé par défaut dans l'image Docker Hub wordpress ). Ce n'est pas la fin du monde, mais j'espérais exécuter quelques commandes à chaque fois que cela montait pour que je puisse simplement monter et descendre les conteneurs de manière transparente sans avoir à me frapper.

Juste mes deux cents: j'ai atterri ici car je dois actuellement activer manuellement les modules Apache à chaque fois que je lance le conteneur (SSL n'est pas activé par défaut dans l'image Docker Hub wordpress ). Ce n'est pas la fin du monde, mais j'espérais exécuter quelques commandes à chaque fois que cela montait pour que je puisse simplement monter et descendre les conteneurs de manière transparente sans avoir à me frapper.

Eh bien, cela pourrait être facilement résolu si vous créez une nouvelle image basée sur l'image wordpress, qui a les modules dont vous avez besoin activés. Ensuite, utilisez cela à la place, par exemple pour un fichier docker:

FROM wordpress:php7.1
RUN a2enmod ssl

Une autre solution serait de télécharger le Dockerfile wordpress et d'y ajouter l'activation du module. Ensuite, produisez une nouvelle image pour vous-même à l'aide de docker build. Par exemple, voici le Dockerfile pour wordpress 5.2 avec php 7.1:

wordpress dockerfile

vous pouvez activer plus de modules dans la ligne 63 ou exécuter la génération ssl.

Tout cela n'est pas le cas dont je pense que nous discutons ici. Le problème est de créer des hooks dynamiques dans le cycle de vie du conteneur, comme quand il commence se termine, etc.

Ce serait un bel ajout à docker-compose!

Des réponses comme celles de ce fil sont la raison pour laquelle Kubernetes conserve «tout» l'argent que produit Docker (technologie), et ce n'est pas une mauvaise chose, espérons que quelqu'un achètera bientôt Docker (entreprise) et changera la façon dont les propositions / demandes de la communauté sont les bienvenues / analysé ...

Des réponses comme celles de ce fil sont la raison pour laquelle Kubernetes conserve _ "tout" _ l'argent que produit Docker (technologie), et ce n'est pas une mauvaise chose, espérons que quelqu'un achètera bientôt Docker (entreprise) et changera la façon dont les propositions / demandes de la communauté sont les bienvenus / analysés ...

J'ai écrit un critique similaire, sans aucune déclaration offensive (c'était dans le sens des projets _open source qui ne sont pas entièrement open source dont les responsables ignorent les arguments sans autre raison que de montrer combien d'argon technique ils possèdent_), il a reçu beaucoup de soutien , et le message a été supprimé.

Cela montre quel genre de personnes arrogantes se cache derrière cela.

Lorsque votre communauté exige quelque chose pendant 4 ans et que vous (Docker) fermez les yeux, cela montre que vous ne regardez pas dans la même direction qu'eux: /

Et maintenant, Docker a abandonné et vendu.
Parce qu'ils ne pouvaient pas écouter ... ils ont perdu.

Honte - mais bon ho.

C'est vraiment dommage que quelque chose comme ça n'existe pas. J'aurais aimé pouvoir créer des hooks onFailure , qui pourraient avoir lieu lorsque les vérifications de l'état échouent.

c'est à dire

services:
  app:
    image: myapp:latest
    hooks:
      onFailure:
        - # Call a monitoring service (from the host machine) to tell it that the service is offline.

Cela serait utile pour les moments où l'application ne se lie pas à un socket / port. Kubernetes est probablement la voie à suivre, ici, mais il s'agit d'un changement d'infrastructure assez important et excessif pour un très petit environnement.

Éditer:
Pour contourner cela, j'ai fini par mettre à jour le point d'entrée de mon conteneur pour "envelopper" la fonctionnalité de surveillance. c'est à dire

# /app/bin/run_with_monitor
#!/bin/bash
set -eE

updateMonitoringSystem() {
 # do something here... This is run from the container, though, unfortunately.
 if [[ $? -eq 1 ]]; then
  # Failed!
 else
  # All is good!
 fi
}

trap 'updateMonitoringSystem' EXIT

$@
# Dockerfile
....
CMD ["/app/bin/run_with_monitor", "./my-app"

Pourtant, ce serait bien de faire cela _sans_ avoir à modifier l'image.

: man_shrugging: Je suis venu chercher cette fonctionnalité de base, que le concurrent (Kubernetes) a, et à la place j'ai trouvé un feu de benne à ordures.

C'est vraiment dommage, maintenant je dois maintenir des images docker séparées pour les tester localement.

Bonne année: roll_eyes:

image

@LukeStonehm pareil ici. Nécessaire d'effectuer UNE commande après que le conteneur a été levé, mais a été traité avec des déchets chauds. Je n'ai vraiment pas envie de gérer mes propres images et fichiers docker lorsqu'une image officielle me permet d'atteindre 90% ou plus du chemin.

Un nombre important de programmes dépendent de certains services pour exister au démarrage. Par exemple une base de données MySQL ou MongoDB.

Par conséquent, il n'y a pas de manière sensée d'utiliser docker-compose dans ces cas.

Au lieu de cela, les utilisateurs doivent:

  • Apprenez à écrire Dockerfiles (et à programmer)
  • Apprenez à créer Docker images
  • Créez Dockerfiles héritant des images d'origine, en ajoutant du code pour vous assurer que les conteneurs attendent les uns les autres
  • Vérifiez régulièrement les mises à jour de sécurité des images de base
  • Modifiez régulièrement le Dockerfiles pour appliquer les mises à jour
  • Construisez régulièrement Docker images partir de ces Dockerfiles

Et ça craint parce que:

  • Vous perdez énormément de temps à apprendre des choses dont vous n'avez peut-être même pas besoin autrement
  • Vous gaspillez régulièrement des ressources matérielles en construisant et en stockant vous-même Docker images ou même en les téléchargeant / téléchargeant (tirant / poussant)
  • Vous perdez régulièrement du temps à écrire ces Dockerfiles , à les construire, à les tester, à les réparer etc ...
  • Vous compromettez potentiellement la sécurité de vos images car vous ne savez pas ce que vous faites
  • Vous perdez la possibilité d'exécuter uniquement officiellement vérifié / signé Docker images

Si nous avions une vérification de démarrage, tout cela ne serait pas nécessaire et nous pourrions simplement changer image: mysql:8.0.18 en image: mysql:8.0.19 quand nous le voulons et que ce soit fait!

En réalité, c'est ce qui se passe actuellement dans le monde réel:

  • Les gens créent leur propre Dockerfiles apportant des modifications afin de travailler avec docker-compose
  • Ils construisent leurs images une fois
  • Et ne les corrigez pas régulièrement
  • Les pirates sont heureux

Et vous ne pouvez pas dire que docker-compose n'est censé "faire qu'une seule chose" car il fait déjà à peu près tout. Y compris l'extraction et la construction d'images encore plus important, la spécification des dépendances à l'aide de la propriété depends_on . Il ne s'agit même pas d'implémenter une fonctionnalité complètement nouvelle, mais simplement de passer un autre paramètre à docker .

@ binman-docker @crosbymichael @dmcgowan @ebriney @ehazlett @eunomie @guillaumerose @jeanlaurent @justincormack @lorenrh @manishtomar @olegburov @routelastresort @spencerhcheng @StefanScherer @thaJeztah @tonistiigi @ulyssessouza @aiordache @ chris-Crone @ndeloof
Veuillez reconsidérer cette fonctionnalité ou au moins avoir une discussion appropriée à ce sujet.

La technique task service fonctionne plutôt bien pour moi à ce stade, mais a ses particularités. Nous avons largement appliqué le modèle dans nos fichiers de composition pour les migrations et l'initialisation des applications. mais je suis d'accord qu'un meilleur 'depend_on' qui attendait un bilan de santé réussi ou une sortie / tâche réussie rendrait de nombreuses tâches plus faciles et plus fiables.

Ce serait vraiment un ajout utile.

Je pense qu'il vaut la peine de souligner que Kubernetes a cette fonctionnalité tout au long du cycle de vie postStart.

k8s! = docker-compose. Mauvaise chaîne

Désolé de ne pas être clair, mais mon point était le suivant: Kubernetes prend en charge cela, et comme Kubernetes et Docker compose ont de nombreux cas d'utilisation / objectifs identiques, ce serait un argument pour l'avoir dans compose. Désolé si je n'étais pas clair.

Bonnes nouvelles!!

Je pense que docker nous a entendus (sur cette question et quelques autres). https://www.docker.com/blog/announcing-the-compose-specification/

Essayons de travailler sur la spécification là-bas pour répondre aux besoins de la communauté. Nous pouvons essayer d'en faire une communauté ouverte et conviviale avec ce redémarrage.

Bonnes nouvelles!!

Je pense que docker nous a entendus (sur cette question et quelques autres). https://www.docker.com/blog/announcing-the-compose-specification/

Essayons de travailler sur la spécification là-bas pour répondre aux besoins de la communauté. Nous pouvons essayer d'en faire une communauté ouverte et conviviale avec ce redémarrage.

Quelqu'un a-t-il déjà suggéré ce changement? La liste de diffusion n'est pas encore disponible, donc je pense que le prochain meilleur endroit est ici: https://github.com/compose-spec/compose-spec

Je ne vois pas de problème décrivant ce problème mais je ne sais pas si c'est le bon endroit ...

Edit: j'ai ouvert un numéro sur https://github.com/compose-spec/compose-spec/issues/84.

Vous pouvez utiliser HEALTHCHECK pour faire autre chose comme l'exemple suivant:

Code

Dockerfile

FROM ubuntu

COPY healthcheck.sh /healthcheck.sh
RUN chmod a+x /healthcheck.sh

HEALTHCHECK --interval=5s CMD /healthcheck.sh

CMD bash -c 'set -x; set +e; while true; do cat /test.txt; sleep 3; done'

healthcheck.sh

#/usr/bin/env bash

set -e

FIRST_READY_STATUS_FLAG='/tmp/.FIRST_READY_STATUS_FLAG'

# Health check

echo 'Run command to validate the container status HERE'

# On success
if [ ! -f "${FIRST_READY_STATUS_FLAG}" ]; then
  # On first success...
  touch "${FIRST_READY_STATUS_FLAG}"

  # Run ON_RUN on first health check ok
  if [ ! -z "${DOCKER_ON_RUN}" ]; then
    eval "${DOCKER_ON_RUN}"
  fi
fi
  1. Exécutez le _health check_.

    • En cas d'échec, quitte le script avec le code de sortie 1 .

    • Si le _health check_ est correct, le script continuera.

  2. S'il s'agit du premier _health check OK_ et si la variable d'environnement DOCKER_ON_RUN existe, exécutez-la.

Exemple

docker-compose.yml

version: "3.7"

services:
  test:
    build:
      context: .
    image: test/on-run
    environment:
      DOCKER_ON_RUN: echo x >> /test.txt

Vous pouvez utiliser la variable d'environnement DOCKER_ON_RUN pour transmettre une commande personnalisée à exécuter après l'exécution.

Résultat d'exécution

docker-compose build
docker-compose up

Production:

Creating network "tmp_default" with the default driver
Creating tmp_test_1 ... done
Attaching to tmp_test_1
test_1  | + set +e
test_1  | + true
test_1  | + cat /test.txt
test_1  | cat: /test.txt: No such file or directory
test_1  | + sleep 3
test_1  | + true
test_1  | + cat /test.txt
test_1  | cat: /test.txt: No such file or directory
test_1  | + sleep 3
test_1  | + true
test_1  | + cat /test.txt
test_1  | x
test_1  | + sleep 3
test_1  | + true
test_1  | + cat /test.txt
test_1  | x
test_1  | + sleep 3
test_1  | + true
test_1  | + cat /test.txt
test_1  | x
test_1  | + sleep 3
  • Vous pouvez voir l'erreur cat: /test.txt: No such file or directory jusqu'à ce que le _health check_ soit prêt.
  • Vous ne pouvez voir qu'un seul x intérieur de /test.txt après l'exécution .

J'espère que cela peut aider quelqu'un.

Modifier 1

Si vous n'avez pas besoin d'un _health check_, vous pouvez utiliser le reste du script.

@ reduardo7
Merci pour votre solution de contournement.
Je veux juste ajouter, au cas où vous auriez besoin d'exécuter la commande 1, comme pour la création d'utilisateurs ou etc., vous pouvez monter le volume pour le touch "${FIRST_READY_STATUS_FLAG}"

Beaucoup de ces solutions sont des solutions de contournement valides à ce problème. Par exemple, créer un script de point d'entrée pourrait également résoudre ce problème:
ENTRYPOINT ["./entrypoint.sh"]

qui inclura une logique plus complexe avant d'exécuter le service ou le processus réel.
Ce n'est toujours pas un hook qui nous permettrait d'injecter de la logique dans le cycle de vie du conteneur:

  • avant de créer
  • avant de commencer
  • après avoir commencé
  • avant de détruire
  • même après avoir détruit
  • etc ...

Je sais que tout ce qui précède n'est pas significatif, mais j'espère que vous comprenez l'image car c'est le but.
Cela pourrait également être inclus dans docker-compose avec une directive comme:

lifecycle:
    before_start: "./beforeStartHook.sh"
    after_destroy: "./afterDestroyHook.sh"

ou même comme ça:

hooks:
    before_destroy: "./beforeDestroyHook.sh"
    before_create: "./fixFsRights.sh"

Je ne parviens pas à écraser le fichier qui nécessite une autorisation root à l'aide d'un script hook ou d'une approche de script bootstrap, car nous démarrons le conteneur en tant qu'utilisateur non root

Wow, une telle fonctionnalité de base et toujours pas implémentée.

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