Różnica między RUN a CMD w Dockerfile

294

Jestem mylić o tym, kiedy należy używać CMDvs RUN. Na przykład, aby wykonać polecenia bash / shell (tj. ls -la) Zawsze używałbym CMDlub czy jest sytuacja, w której używałbym RUN? Próbowanie zrozumienia najlepszych praktyk dotyczących tych dwóch podobnych Dockerfiledyrektyw.

TakeSoUp
źródło

Odpowiedzi:

426

RUN to krok kompilacji obrazu, stan kontenera po RUNkomendzie zostanie zatwierdzony do obrazu kontenera. Plik Docker może składać się z wielu RUNkroków jeden na drugim, aby zbudować obraz.

CMD to polecenie domyślnie wykonywane przez kontener podczas uruchamiania wbudowanego obrazu. Plik Docker będzie używał tylko CMDzdefiniowanej wersji końcowej . CMDMoże być zmienione, gdy zaczyna się pojemnik docker run $image $other_command.

ENTRYPOINT jest również ściśle powiązany CMDi może modyfikować sposób, w jaki kontener rozpoczyna obraz.

Matt
źródło
15
robisz wszystko, co RUNkonieczne, aby skonfigurować środowisko, a twój (tylko) CMD uruchamia proces działający w twoim kontenerze, na przykład dla nginx, wyciąg z github.com/nginxinc/docker-nginx/blob/… widzisz linięCMD ["nginx", "-g", "daemon off;"]
użytkownik2915097
„Plik dokowania może mieć tylko jeden CMD” - technicznie nie jest to prawda, ale w rzeczywistości wszystkie oprócz jednego zostaną zignorowane. Zobacz odpowiedź GingerBeer.
Colm Bhandal
„Plik Docker użyje tylko ostatecznego zdefiniowanego CMD”? tak naprawdę, ostateczna zdefiniowana CMD zostanie wykorzystana do uruchomienia obrazu jako kontenera, prawda?
Paul Cheung
1
Tak @paulcheung ostatnie polecenie w pliku dokera jest zapisywane na obrazie i jest poleceniem, które kontener wykonuje domyślnie po uruchomieniu wbudowanego obrazu.
Matt
126

RUN - polecenie uruchamia się podczas budowania obrazu dokera.

CMD - polecenie uruchamia się podczas uruchamiania utworzonego obrazu dokera.

Nisal Edu
źródło
67

Uważam, że ten artykuł jest bardzo pomocny w zrozumieniu różnicy między nimi:

RUN - instrukcja RUN pozwala zainstalować aplikację i wymagane do tego pakiety. Wykonuje wszelkie polecenia na bieżącym obrazie i tworzy nową warstwę, zatwierdzając wyniki. Często w Dockerfile znajdziesz wiele instrukcji RUN.

CMD - Instrukcja CMD pozwala ustawić domyślne polecenie, które zostanie wykonane tylko po uruchomieniu kontenera bez podania polecenia. Jeśli kontener Docker działa z poleceniem, polecenie domyślne zostanie zignorowane. Jeśli plik Docker ma więcej niż jedną instrukcję CMD, wszystkie
instrukcje CMD oprócz ostatnich są ignorowane.

wróżka
źródło
13

RUN - zainstaluj Python, twój kontener ma teraz wypalonego Pythona na obrazku
CMD - python hello.py, uruchom swój ulubiony skrypt

Rohit Salecha
źródło
CMD - Zainstaluj Python, czy mój kontener nie ma już spalonego Pythona na jego obrazie?
Carlos Fontes
RUN utworzy warstwę obrazu Pythona, CMD po prostu wykona polecenie, a nie utworzy obrazu
Rohit Salecha
8

Polecenie RUN: polecenie RUN po prostu wykona polecenie domyślne, gdy budujemy obraz. Zatwierdzi także zmiany obrazu w następnym kroku.

Może być więcej niż 1 polecenie RUN, aby pomóc w budowaniu nowego obrazu.

Polecenie CMD: Polecenia CMD po prostu ustawiają domyślne polecenie dla nowego kontenera. Nie zostanie to wykonane podczas kompilacji.

Jeśli plik dokera zawiera więcej niż 1 komendę CMD, wszystkie są ignorowane, z wyjątkiem ostatniej. Ponieważ to polecenie niczego nie wykona, po prostu ustaw domyślne polecenie.

Piwo imbirowe
źródło
6

Uwaga: Nie myl RUN z CMD. RUN faktycznie uruchamia polecenie i zatwierdza wynik; CMD nie wykonuje niczego w czasie kompilacji, ale określa zamierzoną komendę dla obrazu.

z odwołania do pliku dokera

https://docs.docker.com/engine/reference/builder/#cmd

Elsayed
źródło
4

RUN : Może być wiele i jest wykorzystywany w procesie kompilacji , np. Instaluje wiele bibliotek

CMD : Można mieć tylko 1, który jest Twój wykonać punkt początkowy (np ["npm", "start"], ["node", "app.js"])

Xin
źródło
2

Odpowiedzi na RUN i CMD są wystarczające . Chcę tylko dodać kilka słów do ENTRYPOINT . Argumenty CMD można nadpisywać argumentami wiersza poleceń, a argumenty ENTRYPOINT są zawsze używane.

Ten artykuł jest dobrym źródłem informacji.

Milo Lu
źródło
2

Istniejące odpowiedzi obejmują większość tego, czego potrzebowałby każdy, kto spojrzy na to pytanie. Więc po prostu zajmę się niektórymi niszowymi obszarami dla CMD i RUN.

CMD: Duplikaty są dozwolone, ale marnotrawne

GingerBeer robi ważny punkt: nie popełnisz żadnych błędów, jeśli włożysz więcej niż jeden CMD - ale marnowanie tego. Chciałbym rozwinąć przykład:

FROM busybox
CMD echo "Executing CMD"
CMD echo "Executing CMD 2"

Jeśli wbudujesz to w obraz i uruchomisz kontener na tym obrazie, to jak stwierdza GingerBeer, tylko ostatnia CMD zostanie uwzględniona. Wyjście tego kontenera będzie:

Wykonywanie CMD 2

Myślę, że „CMD” ustawia pojedynczą zmienną globalną dla całego budowanego obrazu, więc kolejne instrukcje „CMD” po prostu nadpisują wszelkie wcześniejsze zapisy do tej zmiennej globalnej, a na ostatecznym obrazie, który jest zbudowany ostatni do pisania wygrywa. Ponieważ plik Docker jest wykonywany w kolejności od góry do dołu, wiemy, że najniższy CMD to ten, który otrzymuje ten końcowy „zapis” (mówiąc metaforycznie).

RUN: polecenia mogą nie zostać wykonane, jeśli obrazy są buforowane

Subtelną kwestią, na którą należy zwrócić uwagę na RUN, jest to, że jest on traktowany jako czysta funkcja, nawet jeśli występują skutki uboczne, i dlatego jest buforowany. Oznacza to, że jeśli RUN miał jakieś skutki uboczne, które nie zmieniają obrazu wynikowego, a ten obraz został już zbuforowany, RUN nie zostanie wykonany ponownie, więc efekty uboczne nie wystąpią przy kolejnych kompilacjach. Na przykład weź ten plik Docker:

FROM busybox
RUN echo "Just echo while you work"

Przy pierwszym uruchomieniu otrzymasz dane wyjściowe takie jak ten, z różnymi identyfikatorami alfanumerycznymi:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Running in ed37d558c505
Just echo while you work
Removing intermediate container ed37d558c505
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest

Zauważ, że instrukcja echa została wykonana powyżej. Przy drugim uruchomieniu używa pamięci podręcznej i nie zobaczysz echa w wynikach kompilacji:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Using cache
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest
Colm Bhandal
źródło