2014-12-17 9 views
26

Mam plik Docker próbuje wdrożyć kod Django do pojemnikaJak zaktualizować kod z Git do pojemnika Docker

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 

A potem budować mój kod jako docker build -t dockerhubaccount/demo:v1 ., a to ciągnie mój kod z Bitbucket do pojemnik. Uruchomiłem to jako docker run -p 8000:8080 -td felixcheruiyot/demo:v1 i wszystko wydaje się działać dobrze.

Teraz chcę zaktualizować kod czyli od użyłem git clone ..., mam ten błąd:

  • Jak mogę zaktualizować swój kod, gdy mam nowe rewizje i na pojemnikach Döcker zbudować statki z nowym kodem (uwaga: po uruchomieniu kompilacji nie pobiera go z powodu pamięci podręcznej).
  • Jaki jest najlepszy przepływ pracy dla tego rodzaju podejścia?

Odpowiedz

20

Istnieje kilka metod, z których można korzystać.

  1. Możesz użyć docker build --no-cache, aby uniknąć korzystania z pamięci podręcznej klonu Git.
  2. Polecenie startowe wywołuje git pull. Więc zamiast uruchamiać python manage.py, będziesz miał coś takiego jak CMD cd /repo && git pull && python manage.py lub użyj skryptu startowego, jeśli rzeczy są bardziej złożone.

Preferuję 2. Możesz także uruchomić zadanie cron, aby zaktualizować kod w swoim kontenerze, ale to trochę więcej pracy i idzie nieco wbrew filozofii Docker.

+2

Ja wezmę 2 za odpowiedź. Myślę, że ma to więcej sensu, ponieważ uruchomienie --no-cache zainstaluje wszystko jako świeże, a nie dobre podejście. Dziękuję za Twój wkład. –

+0

co jeśli ktoś wykona 'docker exec -it con/tainer bash' - to uruchomi' bash' zamiast tego, co jest określone w 'CMD'. Wydaje mi się, że obie opcje są dość nieoptymalne, a to musi być bardzo powszechny problem - uważam, że powinien istnieć sposób wyłączenia pamięci podręcznej w środku 'Dockerfile'. – avloss

5

Inne rozwiązanie.

Polecenie budowania Docker wykorzystuje pamięć podręczną, o ile ciąg instrukcji jest dokładnie taki sam, jak ciąg znaków w pamięci podręcznej. Tak więc, jeśli napiszesz

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

Przy następnej aktualizacji, zmienia się w następujący sposób.

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

Może to uniemożliwić dokerowi korzystanie z pamięci podręcznej.

+0

Myślę, że najlepszą odpowiedzią jest to. Dzięki tej metodzie możemy wyłączyć pamięć podręczną tylko w odpowiednim miejscu. – makerj

+0

należy zauważyć, że spowoduje to wszystko po tym, jak ta linia zostanie przebudowana. Dobra, jeśli twój ciąg git jest ostatnią linią, jak w pytaniu OP.Mogłoby być źle, jeśli twój ciąg git jest wcześniej w Dockerfile – JHowIX

10

Polecam wypisanie kodu na swoim komputerze i dodanie go do obrazu. W ten sposób będzie aktualizowany po każdej zmianie. Ponadto podczas projektowania można powiązać montowanie katalogu źródłowego z katalogiem kodu w kontenerze, co oznacza, że ​​wszelkie zmiany są natychmiast odzwierciedlane w kontenerze.

Polecenie docker dla repozytoriów git, które sprawdza ostatnią aktualizację, byłoby jednak bardzo przydatne!

2

Chciałbym zaproponować inne możliwe rozwiązanie. Muszę jednak ostrzec, że to zdecydowanie nie jest "sposób dokowania" robienia rzeczy i opiera się na istnieniu woluminów (które mogą być potencjalnym blokerem w narzędziach takich jak Docker Swarm i Kubernetes)

Podstawowa zasada, że ​​będziemy Wykorzystanie tego faktu jest faktem, że zawartość katalogów kontenerów używanych jako woluminy Docker jest przechowywana w systemie plików hosta. Zapoznaj się z częścią dokumentacji: this.

W twoim przypadku uczynisz /opt/app Docker Volume.Nie musisz bezpośrednio mapować woluminu do lokalizacji w systemie plików hosta, ponieważ jak opiszę poniżej, mapowanie można uzyskać dynamicznie.

Więc dla startowania zostawić Dockerfile dokładnie jak to jest i przełączyć polecenie tworzenia kontenera do czegoś podobnego:

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

Komenda docker inspect -f {{index .Volumes "/opt/webapp"}} some-name będzie wydrukować pełną ścieżkę systemu plików na komputerze, gdzie jest przechowywany kod (this jest tam, gdzie wziąłem trik kontrolny).

Uzbrojony w tę wiedzę, wszystko co musisz zrobić, to zastąpić ten kod i cały zestaw. Więc bardzo prosty skrypt wdrożyć byłoby coś takiego:

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

korzyści otrzymasz z podejściem jak to jest:

  • Nie ma potencjalnie kosztowne cacheless obraz odbudowuje
  • Nie ma trzeba przenieść specyficzne informacje o aplikacji do komendy run. Dockerfile jest jedynym źródłem potrzebne do instrumentacji Aplikacja

UPDATE

można osiągnąć takie same wyniki już wspomniano powyżej, stosując docker cp (począwszy Döcker 1.8). W ten sposób kontener nie musi mieć woluminów, a kod można zamienić w kontenerze, tak jak w systemie plików hosta.

Oczywiście, jak wspomniałem na początku odpowiedzi, nie jest to "sposób dokowania" robienia rzeczy, który zaleca, aby pojemniki były niezmienne i powtarzalne.

+0

tylko notatkę ... niezmienne kontenery doków? w jaki sposób radzi sobie ze zmieniającym się środowiskiem Pythona, gdy aktualizacja aplikacji używa nowych zależności? – Yoeri

+0

@ Yoeri Sposób dokowania zaleca użycie * nowych * kontenerów, gdy coś się zmieni. Oznacza to, że gdy aplikacja zostanie zaktualizowana w dowolny sposób (czy to kod aplikacji, zależności, konfiguracja itp.), Należy utworzyć nowy kontener. Celem jest uzyskanie pełnej odtwarzalności kontenera – geoand

+1

, więc lepiej byłoby użyć osobnego kontenera (lub hosta) ze źródłami i środowiskiem i dzielić się tymi woluminami. Zawsze znajduję pytanie o zmianę kodu źródłowego, nigdy o zmianę zależności. .. – Yoeri

0

Jeśli używasz GitHub, możesz użyć interfejsu API GitHub, aby nie buforować określonych poleceń RUN.

Musisz mieć JQ zainstalowane do analizowania JSON: apt-get install -y jq

Przykład:

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

W Dockerfile (ARG polecenie powinno być tuż przed RUN):

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

lub jeśli nie chcę instalować jq:

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

Jeśli repozytorium ma nowe zatwierdzenia, zostanie wykonane git clone.

+0

Możesz również użyć polecenia 'ADD', aby" budować dokowanie ", pobierać bieżący ref HEAD z interfejsu API za każdym razem . Wtedy, gdy zmieni się HEAD, pamięć podręczna zostanie unieważniona. http://stackoverflow.com/questions/36996046/how-to-prevent-dockerfile-caching-git-clone/39278224#39278224 – anq

Powiązane problemy