web-dev-qa-db-fra.com

Comment mettre à jour le code de Git vers un conteneur Docker

J'ai un fichier Docker essayant de déployer du code Django dans un conteneur

FROM ubuntu:latest
MAINTAINER { myname }

#RUN echo "deb http://archive.ubuntu.com/ubuntu/ $(lsb_release -sc) main universe" >> /etc/apt/sou$

RUN apt-get update

RUN DEBIAN_FRONTEND=noninteractive apt-get install -y tar git curl dialog wget net-tools nano buil$
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python python-dev python-distribute python-p$

RUN mkdir /opt/app
WORKDIR /opt/app

#Pull Code
RUN git clone [email protected]/{user}/{repo}

RUN pip install -r website/requirements.txt

#EXPOSE = ["8000"]
CMD python website/manage.py runserver 0.0.0.0:8000

Et puis je construis mon code en tant que docker build -t dockerhubaccount/demo:v1 ., et cela extrait mon code de Bitbucket vers le conteneur. Je le lance en tant que docker run -p 8000:8080 -td felixcheruiyot/demo:v1 et les choses semblent bien fonctionner.

Maintenant, je veux mettre à jour le code i.e depuis que j'ai utilisé git clone ..., j'ai cette confusion:

  • Comment puis-je mettre à jour mon code lorsque j'ai de nouveaux commits et que lorsque les conteneurs Docker sont générés, il est livré avec le nouveau code (note: lorsque j'exécute build, il ne le récupère pas à cause du cache).
  • Quel est le meilleur flux de travail pour ce type d’approche?
28
Cheruiyot Felix

Il existe plusieurs approches que vous pouvez utiliser.

  1. Vous pouvez utiliser docker build --no-cache pour éviter d'utiliser le cache du clone Git.
  2. La commande de démarrage appelle git pull. Ainsi, au lieu d'exécuter python manage.py, vous utiliseriez quelque chose comme CMD cd /repo && git pull && python manage.py ou utilisez un script de démarrage si les choses sont plus complexes.

J'ai tendance à préférer 2. Vous pouvez également exécuter un travail cron pour mettre à jour le code de votre conteneur, mais cela demande un peu plus de travail et va un peu à l'encontre de la philosophie Docker.

21
seanmcl

Je vous recommande de vérifier le code sur votre hôte et le COPY dans l'image De cette façon, il sera mis à jour chaque fois que vous apporterez un changement. En outre, pendant le développement, vous pouvez lier le répertoire source par-dessus le répertoire de code du conteneur, ce qui signifie que toutes les modifications sont immédiatement reflétées dans le conteneur.

Une commande docker pour les dépôts git qui vérifie la dernière mise à jour serait très utile cependant!

10
Adrian Mouat

Une autre solution.

La commande de construction Docker utilise le cache tant qu'une chaîne d'instruction est identique à celle de l'image mise en cache. Donc, si vous écrivez 

RUN echo '2014122400' >/dev/null && git pull ...

Lors de la prochaine mise à jour, vous changez comme suit.

RUN echo '2014122501' >/dev/null && git pull ...

Cela peut empêcher le menu fixe d'utiliser le cache.

6
takaomag

Je voudrais proposer une autre solution possible. Je dois toutefois avertir que ce n’est certainement pas la "manière de docker" de faire les choses et repose sur l’existence de volumes (qui pourrait être un bloqueur potentiel dans des outils comme Docker Swarm et Kubernetes)

Le principe de base dont nous allons tirer parti est le fait que le contenu des répertoires de conteneur utilisés en tant que volumes Docker est en réalité stocké dans le système de fichiers de l'hôte. Découvrez this une partie de la documentation.

Dans votre cas, vous feriez /opt/app un volume Docker. Vous n'avez pas besoin de mapper explicitement le volume sur un emplacement du système de fichiers de l'hôte car, comme je le décrirai ci-dessous, le mappage peut être obtenu de manière dynamique.

Donc, pour commencer, laissez votre fichier Dockerfile exactement tel qu’il est et passez votre commande de création de conteneur à quelque chose comme:

docker run -p 8000:8080 -v /opt/app --name some-name -td felixcheruiyot/demo:v1

La commande docker inspect -f {{index .Volumes "/opt/webapp"}} some-name imprimera le chemin d'accès complet au système de fichiers sur l'hôte où votre code est stocké ( this est l'endroit où j'ai pris l'astuce d'inspecter). 

Armé de cette connaissance, tout ce que vous avez à faire est de remplacer ce code et votre ensemble… .. Donc, un script de déploiement très simple serait quelque chose comme:

code_path=$(docker inspect -f {{index .Volumes "/opt/webapp"}} some-name)
rm -rfv $code_path/*
cd $code_path
git clone [email protected]/{user}/{repo}

Les avantages que vous obtenez avec une telle approche sont les suivants:

  • Il n'y a pas de reconstruction d'image sans cache potentiellement coûteuse 
  • Il n'est pas nécessaire de déplacer les informations d'exécution spécifiques à l'application dans la commande d'exécution. Le Dockerfile est la seule source d’information nécessaire pour l’instrumentation de l’application

METTRE À JOUR

Vous pouvez obtenir les mêmes résultats que ceux mentionnés ci-dessus avec docker cp (à partir de Docker 1.8). De cette façon, le conteneur n'a pas besoin de volumes et vous pouvez remplacer le code dans le conteneur comme vous le feriez sur le système de fichiers hôte.

Bien sûr, comme je l’ai mentionné au début de la réponse, ce n’est pas la "manière docker" de faire les choses, qui préconise que les conteneurs soient immuables et reproductibles.

2
geoand

Si vous utilisez GitHub, vous pouvez utiliser l'API GitHub pour ne pas mettre en cache des commandes RUN spécifiques.

Vous devez avoir installé jq pour pouvoir analyser JSON: apt-get install -y jq

Exemple:

docker build --build-arg SHA=$(curl -s 'https://api.github.com/repos/Tencent/mars/commits' | jq -r '.[0].sha') -t imageName .

Dans Dockerfile (la commande ARG devrait être juste avant RUN):

ARG SHA=LATEST
RUN SHA=${SHA} \
    git clone https://github.com/Tencent/mars.git

Ou si vous ne voulez pas installer jq:

SHA=$(curl -s 'https://api.github.com/repos/Tencent/mars/commits' | grep sha | head -1)

Si un référentiel a de nouveaux commits, git clone sera exécuté.

0
Michal Z m u d a