J'ai un Dockerfile que je mets en place pour installer un environnement python vanille (dans lequel j'installerai une application, mais à une date ultérieure).
FROM ubuntu:12.04
# required to build certain python libraries
RUN apt-get install python-dev -y
# install pip - canonical installation instructions from pip-installer.org
# http://www.pip-installer.org/en/latest/installing.html
ADD https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py /tmp/ez_setup.py
ADD https://raw.github.com/pypa/pip/master/contrib/get-pip.py /tmp/get-pip.py
RUN python /tmp/ez_setup.py
RUN python /tmp/get-pip.py
RUN pip install --upgrade pip
# install and configure virtualenv
RUN pip install virtualenv
RUN pip install virtualenvwrapper
ENV WORKON_HOME ~/.virtualenvs
RUN mkdir -p $WORKON_HOME
RUN source /usr/local/bin/virtualenvwrapper.sh
La construction s'exécute correctement jusqu'à la dernière ligne, où j'obtiens l'exception suivante:
[previous steps 1-9 removed for clarity]
...
Successfully installed virtualenvwrapper virtualenv-clone stevedore
Cleaning up...
---> 1fc253a8f860
Step 10 : ENV WORKON_HOME ~/.virtualenvs
---> Running in 8b0145d2c80d
---> 0f91a5d96013
Step 11 : RUN mkdir -p $WORKON_HOME
---> Running in 9d2552712ddf
---> 3a87364c7b45
Step 12 : RUN source /usr/local/bin/virtualenvwrapper.sh
---> Running in c13a187261ec
/bin/sh: 1: source: not found
Si je suis ls
dans ce répertoire (juste pour tester que les étapes précédentes ont été validées), je peux voir que les fichiers existent comme prévu:
$ docker run 3a87 ls /usr/local/bin
easy_install
easy_install-2.7
pip
pip-2.7
virtualenv
virtualenv-2.7
virtualenv-clone
virtualenvwrapper.sh
virtualenvwrapper_lazy.sh
Si j'essaye d'exécuter la source
commande, j'obtiens la même erreur «introuvable» que ci-dessus. Cependant, si je lance une session shell interactive, la source fonctionne:
$ docker run 3a87 bash
source
bash: line 1: source: filename argument required
source: usage: source filename [arguments]
Je peux exécuter le script à partir d'ici, puis accéder avec bonheur workon
, mkvirtualenv
etc.
J'ai fait quelques recherches, et au début, il semblait que le problème pourrait résider dans la différence entre bash en tant que shell de connexion Ubuntu et dash en tant que shell système Ubuntu , dash ne prenant pas en charge la source
commande.
Cependant, la réponse à cela semble être d'utiliser "." au lieu de source
, mais cela provoque juste l'explosion du Docker avec une exception de panique.
Quelle est la meilleure façon d'exécuter un script shell à partir d'une instruction Dockerfile RUN pour contourner ce problème (je suis en train d'exécuter l'image de base par défaut pour Ubuntu 12.04 LTS).
CMD source activate django-py35
Réponses:
RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh"
la source
source
du tout, vs justebash /usr/local/bin/virtualenvwrapper.sh
, dans ce cas?RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh; my_command; my_command; my_command;"
/bin/sh -c
c'est le shell par défaut, cette "forme shell" de RUN se traduit parRUN ["/bin/sh", "-c", "/bin/bash" "-c" "source /usr/local/bin/virtualenvwrapper.sh"]
. Vous devriez aller de l'avant et utiliser la "forme exécutable" de RUN afin de pouvoirsh
sortir comme çaRUN ["/bin/bash" "-c" "source /usr/local/bin/virtualenvwrapper.sh"]
bash
imbriqué dans unsh
et doit donc être évité.Réponse originale
Cela devrait fonctionner pour chaque image de base de docker Ubuntu. J'ajoute généralement cette ligne pour chaque Dockerfile que j'écris.
Modifier par un spectateur concerné
Si vous souhaitez obtenir l'effet «utiliser
bash
au lieu desh
tout au long de ce Dockerfile» sans altérer et éventuellement endommager * le système d'exploitation à l'intérieur du conteneur, vous pouvez simplement dire à Docker votre intention . Cela se fait comme suit:Plus de détails dans cette réponse ci-dessous. https://stackoverflow.com/a/45087082/117471
la source
ln -snf /bin/bash /bin/sh
sh
àbash
ln -s /bin/bash /bin/sh
c'est une terrible idée. ubuntu cible / bin / sh pour se lancer pour une raison. dash est un shell entièrement posix qui est plus rapide que bash. lier / bin / sh à bash réduira considérablement les performances de votre serveur. citer: wiki.ubuntu.com/DashAsBinShsh
shell, mais que vous le souhaitezbash
, la solution appropriée consiste àsh
invoquer le processus debash
manière ponctuelle, par exemplebash -c 'source /script.sh && …'
, ou vous pouvez même aller jusqu'à éviter complètement les bashismes (commesource
), et à la place choisissez de n'utiliser que des équivalents POSIX valides, par exemple. /script.sh
. (Attention à l'espace après le.
!) Enfin, si votre script est exécutable (pas seulement sourceable), ne faites jamais mentir votre script avec un#!/bin/sh
shebang s'il n'est pas réellement compatible sh. Utilisez#!/bin/bash
plutôt.Le shell par défaut de l'
RUN
instruction est["/bin/sh", "-c"]
.En utilisant l' instruction SHELL , vous pouvez modifier le shell par défaut pour les
RUN
instructions suivantes dans Dockerfile:Maintenant, le shell par défaut a changé et vous n'avez pas besoin de le définir explicitement dans chaque instruction RUN
Remarque supplémentaire : vous pouvez également ajouter une
--login
option permettant de démarrer un shell de connexion. Cela signifie que,~/.bachrc
par exemple, serait lu et que vous n'avez pas besoin de le source explicitement avant votre commandela source
--login
- je viens de comprendre cela moiSHELL ["/bin/bash", "-c", "-l"]
j'ai pu utiliser d'autres mises à jour du fichier .bashrc, ce qui m'a permis d'exécuter facilement les commandes asdf.J'ai eu le même problème et pour exécuter l'installation de pip dans virtualenv, j'ai dû utiliser cette commande:
J'espère que ça aide.
la source
RUN /bin/bash -c "source /opt/ros/melodic/setup.bash && \ cd /home && \ git clone https://angelos.p:[email protected]/inno/grpc-comms.git && \ cd grpc-comms && \ mkdir build && \ cd build && \ cmake .. && make"
La manière la plus simple est d'utiliser l'opérateur point à la place de la source, qui est l'équivalent sh de la
source
commande bash :Au lieu de:
Utilisation:
la source
.
/source
accepte également les paramètres de position après le nom de fichiersource
ou.
sont perdues à la fin de la commande RUN. Voir: stackoverflow.com/a/40045930/19501Si vous utilisez Docker 1.12 ou plus récent, utilisez simplement
SHELL
!Réponse courte:
général:
pour python vituralenv:
Longue réponse:
depuis https://docs.docker.com/engine/reference/builder/#/shell
la source
En m'appuyant sur les réponses de cette page, j'ajouterais que vous devez être conscient que chaque instruction RUN s'exécute indépendamment des autres
/bin/sh -c
et qu'elle n'obtiendra donc aucune variable d'environnement qui proviendrait normalement des shells de connexion.La meilleure façon que j'ai trouvée jusqu'à présent est d'ajouter le script à
/etc/bash.bashrc
, puis d'appeler chaque commande en tant que connexion bash.Vous pouvez par exemple installer et configurer virtualenvwrapper, créer l'environnement virtuel, l'activer lorsque vous utilisez une connexion bash, puis installer vos modules python dans cet environnement:
La lecture du manuel sur les fichiers de démarrage bash permet de comprendre ce qui provient quand.
la source
ADD env-file /etc/profile.d/installerenv.sh
RUN /bin/bash --login -c 'env'
RUN /bin/bash -c 'rm /etc/profile.d/installerenv.sh'
si son cas d'utilisation ajoute plus de variables d'environnement d'injection à la perspective de construction de docker comme la mienne, je recommanderais de consulter docs.docker.com/compose/yml / # fichier-env aussi.RUN
commande, ce qui signifie que vous ne pouvez pas installer beaucoup de dépendances de projet, puis copier sur le code source et profiter des avantages de Mise en cache des étapes intermédiaires de Docker. Il réinstallera toutes les dépendances du projet à chaque fois./etc/bashrc
pour Redhat, au lieu de/etc/bash.bashrc
comme mentionné ci-dessus (pour Ubuntu)Selon https://docs.docker.com/engine/reference/builder/#run, le shell [Linux] par défaut pour
RUN
est/bin/sh -c
. Vous semblez vous attendre à des bashismes, vous devez donc utiliser la "forme exec" deRUN
pour spécifier votre shell.Sinon, l'utilisation de la «forme shell» de RUN et la spécification d'un shell différent aboutissent à des shells imbriqués.
Si vous avez plus d'une commande qui nécessite un shell différent, vous devriez lire https://docs.docker.com/engine/reference/builder/#shell et changer votre shell par défaut en plaçant ceci avant vos commandes RUN:
Enfin, si vous avez placé quelque chose dans le
.bashrc
fichier de l'utilisateur root dont vous avez besoin, vous pouvez ajouter l'-l
indicateur à la commandeSHELL
ouRUN
pour en faire un shell de connexion et vous assurer qu'il est fourni.Remarque: j'ai intentionnellement ignoré le fait qu'il est inutile de source un script comme la seule commande dans un RUN.
la source
SHELL ["/bin/sh", "-c", "-l"]
donc il source ~ / .bashrc etc dans le cas où vous avez des paramètres d'environnement depuis le conteneur de base/bin/sh
qui ne résoudra pas le problème de bash non utilisé. De plus, lors de la réalisation d'un,docker build
il est peu probable qu'il y ait quelque chose d'utile dans le .bashrc de l'utilisateur root dont vous avez besoin. Mais, si vous y mettez quelque chose plus tôt dans le Dockerfile (comme peut-être unJAVA_HOME
, alors oui. Je mettrai une note à ce sujet dans ma réponse.Selon la documentation Docker
Voir https://docs.docker.com/engine/reference/builder/#run
la source
Si vous en avez,
SHELL
vous devriez utiliser cette réponse - n'utilisez pas celle qui est acceptée, ce qui vous oblige à mettre le reste du dockerfile dans une seule commande par ce commentaire .Si vous utilisez une ancienne version de Docker et que vous n'y avez pas accès
SHELL
, cela fonctionnera tant que vous n'aurez besoin de rien.bashrc
(ce qui est un cas rare dans Dockerfiles):Notez que
-i
est nécessaire pour que bash lise le fichier rc.la source
Vous voudrez peut-être exécuter
bash -v
pour voir ce qui est recherché.Je ferais ce qui suit au lieu de jouer avec des liens symboliques:
RUN echo "source /usr/local/bin/virtualenvwrapper.sh" >> /etc/bash.bashrc
la source
J'ai également eu des problèmes lors de l'exécution
source
dans un DockerfileCela fonctionne parfaitement pour la construction du conteneur Docker de CentOS 6.6, mais a posé des problèmes dans les conteneurs Debian
C'est comme ça que je l'ai abordé, ce n'est peut-être pas une manière élégante mais c'est ce qui a fonctionné pour moi
la source
Cela peut se produire car il
source
s'agit d'une fonction intégrée à bash plutôt que d'un binaire quelque part sur le système de fichiers. Votre intention est-elle que le script que vous souriez modifie le conteneur par la suite?la source
J'ai fini par mettre mes trucs env et j'ai
.profile
mutéSHELL
quelque chose commela source
Si vous essayez simplement d'utiliser pip pour installer quelque chose dans virtualenv, vous pouvez modifier le PATH env pour qu'il regarde d'abord dans le dossier bin de virtualenv
ENV PATH="/path/to/venv/bin:${PATH}"
Ensuite, toutes les
pip install
commandes qui suivent dans le Dockerfile trouveront d'abord / path / to / venv / bin / pip et l'utiliseront, qui s'installera dans ce virtualenv et non dans le python système.la source