web-dev-qa-db-fra.com

Comment puis-je accéder aux variables d'environnement de l'ensemble Docker à partir d'un travail périodique?

J'ai récemment essayé d'exécuter un travail cron à partir d'un conteneur de docker lié et j'ai rencontré un problème. Mon conteneur docker principal est lié à un conteneur postgres et son numéro de port est défini en tant que variable d'environnement par docker lors de la création des conteneurs. Cette variable d'environnement n'est définie ni dans ~/.profile ni dans aucun autre fichier source que je pourrais charger lors de l'exécution de mon travail cron. Comment puis-je accéder à ces variables d'environnement à partir de mon travail cron?

Merci!

31
Fabio Berger

J'ai rencontré ce même problème. J'ai un conteneur Docker qui exécute cron pour exécuter périodiquement certains scripts Shell. Moi aussi, j'ai eu du mal à comprendre pourquoi mes scripts s'exécutaient correctement lorsque je les exécutais manuellement dans le conteneur. J'ai essayé toutes les astuces de la création d'un script Shell qui s'exécutait en premier pour définir l'environnement, mais ils ne m'ont jamais fonctionné (le plus souvent, j'ai mal agi). Mais j'ai continué à chercher et j'ai trouvé ça et ça fonctionne.

  1. Configurer un script shell de point de départ ou d’entrée pour votre conteneur cron
  2. Faites-en la première ligne à exécuter printenv | grep -v "no_proxy" >> /etc/environment

L'astuce ici est le fichier /etc/environment. Lorsque le conteneur est construit, ce fichier est vide, je pense exprès. J'ai trouvé une référence à ce fichier dans les pages de manuel de cron (8) . Après avoir examiné toutes les versions de cron, elles ont toutes échappé à un fichier /etc/? que vous pouvez utiliser pour alimenter des variables d'environnement avec des processus enfants.

Notez également que j'ai créé mon conteneur Docker pour exécuter cron au premier plan, cron -f. Cela m'a aidé à éviter d'autres astuces avec tail pour garder le conteneur ouvert.

Voici mon fichier entrypoint.sh pour référence et mon conteneur est une image de base debian: jessie.

printenv | grep -v "no_proxy" >> /etc/environment

cron -f

En outre, cette astuce fonctionnait même avec les variables d'environnement définies lors des commandes docker run.

35
Tim Schruben

Je recommanderais d'utiliser declare pour exporter votre environnement et éviter les problèmes d'échappement (en utilisant CMD ou ENTRYPOINT ou directement dans un script d'encapsulation pouvant être appelé par l'un d'eux):

declare -p | grep -Ev 'BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID' > /container.env

Grep -v se charge de filtrer les variables en lecture seule.

Vous pouvez plus tard facilement charger cet environnement comme ceci:

Shell=/bin/bash
BASH_ENV=/container.env
* * * * * root /test-cron.sh
9
Alex Fedulov

Vous pouvez ajouter les variables d'environnement système au sommet d'un fichier crontab en utilisant un script shell wrapper pour exécuter le démon cron. L’exemple suivant est tiré de CentOs 7, 

Dans le fichier de docker

COPY my_cron /tmp/my_cron
COPY bin/run-crond.sh run-crond.sh
RUN chmod -v +x /run-crond.sh
CMD ["/run-crond.sh"]

run_cron.sh:

#!/bin/bash

# prepend application environment variables to crontab
env | egrep '^MY_VAR' | cat - /tmp/my_cron > /etc/cron.d/my_cron

# Run cron deamon
# -m off : sending mail is off 
# tail makes the output to cron.log viewable with the $(docker logs container_id) command
/usr/sbin/crond -m off  && tail -f /var/log/cron.log

Ceci est basé sur un bon article de blog quelque part, mais j'ai perdu le lien. 

3
Michael Moyle

L'environnement est défini, mais n'est pas disponible pour le travail cron. Pour résoudre ce problème, vous pouvez faire ces deux choses simples

1) Enregistrez l’env dans un fichier de votre ENTRYPOINT ou de votre CMD

CMD env > /tmp/.MyApp.env && /bin/MyApp

2) Lisez ensuite env dans votre commande cron comme ceci:

0 5 * * * . /tmp/.MyApp.env; /bin/MyApp
2
Mark Riggins

Pour échapper à tout caractère étrange qui pourrait casser votre script et selon le raisonnement de Réponse de Mark , ajoutez cette ligne à votre entrypoint.sh:

env | sed -r "s/'/\\\'/gm" | sed -r "s/^([^=]+=)(.*)\$/\1'\2'/gm" \ > /etc/environment

Ainsi, si vous avez une variable telle que affinity:container==My container's friend, elle sera convertie en affinity:container='=My container\'s friend et ainsi de suite.

0
Yajo