2014-09-30 11 views
5

Gram z Dockerem i tworzę narzędzie i próbuję napisać regułę, która odbudowuje obraz doka tylko w przypadku zmiany pliku Docker.
Moja struktura projektu wygląda następująco:Doker z make: buduj obraz na Dockerfile change

tree . 
. 
├── Dockerfile 
├── Makefile 
└── project 
    └── 1.js 

My Dockerfile jest dość prosta:

FROM ubuntu 

RUN apt-get update 
RUN apt-get install -y curl 
RUN curl -sL https://deb.nodesource.com/setup | sudo bash - 
RUN apt-get update 
RUN apt-get install -y build-essential nodejs 
VOLUME ["/project"] 
ENTRYPOINT ["cat"] 
CMD ["project/1.js"] 

To właśnie tworzy prostą ubuntu obraz z instalacją nodejs i uruchomić skrypt z katalogu udostępnionego.

Teraz chcę uruchomić ten obraz z pliku Makefile. Kiedy zmieniam plik Dockerfile, chcę go odbudować. Makefile wygląda następująco:

default: run 

run: build 
     docker run -v $(CURDIR)/project:/project app-server 

build: Dockerfile 
     docker build -t app-server . 

Teraz kiedy wykonać polecenie sudo make to odbudować obraz za każdym razem.

Jak zmusić make do wykonania zadania kompilacji tylko po zmianie pliku Dockerfile?

+0

Należy naprawdę spojrzeć na https://docs.docker.com/articles/dockerfile_best-practices/ –

+0

Prawdopodobnie nie trzeba tego robić. 'docker build' wewnętrznie zarządza tego typu zmianą zależności, aby uzyskać w zasadzie ten sam efekt, który próbujesz osiągnąć za pomocą' make'. Jeśli nie potrzebujesz widzieć statusu, możesz użyć opcji '--quiet' razem z'>/dev/null'. – nobar

Odpowiedz

6

Kiedy piszesz:

run: build 
     docker run -v $(CURDIR)/project:/project app-server 

w make Makefile spodziewa się, że przepis zostanie utworzony plik o nazwie run. make sprawdzi znacznik czasu pliku względem znacznika czasu jego plików wymagań wstępnych, aby ustalić, czy przepis musi zostać uruchomiony następnym razem.

Podobnie z celem build masz w makefile.

build: Dockerfile 
     docker build -t app-server . 

Żaden z tych przepisów nie tworzy jednak plików z nazwą celu. Oznacza to, że make nie może użyć znacznika czasu tego pliku, aby określić, czy konieczne jest ponowne uruchomienie receptury. Jako taka marka musi założyć, że musi ponownie uruchomić przepis (ponieważ założenie, że jest inaczej, oznaczałoby, że reguła nigdy nie zostanie uruchomiona).

Jeśli uruchomisz make -rRd zobaczysz, co myślisz, co się dzieje i powinieneś zobaczyć wskazanie, co właśnie powiedziałem.

Rozwiązaniem problemu jest zatem tworzenie plików stempli w każdym z tych celów.

Po prostu dodanie touch [email protected] (opcjonalnie z prefiksem @, aby wyciszyć domyślne echo poleceń, które uruchamia) do każdego z tych obiektów powinno wystarczyć, aby to zadziałało.

takiej sytuacji może warto byłoby umieścić sudo na każdej z linii receptury, które potrzebują go zamiast biegać make z sudo, jeśli nie chcesz, aby pliki znaczek być własnością jako root, jak również.

Dla zapisu jest to omówione w podręczniku GNU Make Manual jako sekcja 4.8 Empty Target Files to Record Events.

5

Twoje "cele" defaultrun i build są "fałszywymi" celami. To abstrakcyjna koncepcja, a nie prawdziwy plik. Takie fałszywe cele, nie powinny mieć przepisu (bo nie można ich zrobić). Powinny one zamiast tego zależeć od rzeczywistych plików lub innych fałszywych celów itd., Ale wszystko musi ostatecznie zależeć tylko od prawdziwych plików.

Twoich fałszywych celów powinno być oznaczone jako takie

.PHONY: default run build 

Prawdziwe cele, z drugiej strony, powinny mieć przepis - przepis sprawia, że ​​ten cel.

Tak więc, najpierw polegaj na fałszywych celach, bez przepisu, na prawdziwym celu (ach).

Następnie prawdziwe cele mają przepisy.

Pisałem kilka wskazówek na makefile enforce library dependency ordering

+0

Chociaż jest to prawidłowe i użyteczne, to nie tylko w ścisłym tego słowa znaczeniu, aby odpowiedzieć na zadane pytanie, ponieważ nie pomaga OP dowiedzieć się, jak uzyskać plik do rozważenia "prawdziwego pliku" celów kierowania dokiem. (Zakładam oczywiście, że docker sam nie tworzy pliku, który może być bezpośrednio zależny.) –

+0

@EtanReisner tak, często nie odpowiadam na pytanie jako postawione, ponieważ myślę arogancko :) lepiej odpowiedzieć na inne pytanie. Guity pod zarzutem Etan! –