Dockerfile'da CMD ve ENTRYPOINT arasındaki fark nedir?


1698

Dockerfiles uygulamasında bana benzeyen iki komut vardır: CMDve ENTRYPOINT. Ama sanırım aralarında (ince?) Bir fark var - aksi takdirde aynı şey için iki komuta sahip olmak mantıklı olmazdı.

Belgeler için CMD

CMD'nin temel amacı, yürütme kabı için varsayılanlar sağlamaktır.

ve için ENTRYPOINT:

ENTRYPOINT, yürütülebilir olarak çalıştırabileceğiniz bir kapsayıcı yapılandırmanıza yardımcı olur.

Peki, bu iki komut arasındaki fark nedir?


12
Bu blog yayını, farklılıklar ve bunların birlikte nasıl kullanılabileceği konusunda iyi bir açıklamaya sahiptir: crosbymichael.com/dockerfile-best-practices.html .
slm

2
^ İşte! Teşekkürler @slm. İşte biraz daha güncel olabilecek başka bir benzer referans: docs.docker.com/reference/builder/#entrypoint
Adam Monsen


1
Bu bağlantı RUN, CMD ve ENTRYPOINT arasında fark sağlar: goinbigdata.com/docker-run-vs-cmd-vs-entrypoint
prafi

1
@JaimeHablutzel Ifade kendinize bir iyilik yapın
Jonathan Komar

Yanıtlar:


1736

Docker'ın varsayılan bir giriş noktası vardır, /bin/sh -cancak varsayılan bir komutu yoktur.

docker run -i -t ubuntu bash Docker'ı şu şekilde çalıştırdığınızda: giriş noktası varsayılan değerdir, /bin/sh -cgörüntü ubuntuve komuttur bash.

Komut giriş noktası üzerinden çalıştırılır. yani, idam edilen gerçek şey /bin/sh -c bash. Bu, Docker'ın RUNkabuğun ayrıştırıcısına güvenerek hızla uygulanmasına izin verdi .

Daha sonra, insanlar bu özelleştirmek edebilmek için istedi, bu yüzden ENTRYPOINTve --entrypointtanıtıldı.

ubuntuYukarıdaki örnekte bundan sonraki her şey komuttur ve giriş noktasına aktarılır. CMDTalimatı kullanırken, sanki yaptığınız gibi docker run -i -t ubuntu <cmd>. <cmd>giriş noktasının parametresi olacaktır.

Bunun yerine bu komutu yazarsanız da aynı sonucu alırsınız docker run -i -t ubuntu. Ubuntu Dockerfile varsayılan bir CMD belirttiği için kapta bir bash kabuğu başlatacaksınız :CMD ["bash"]

Her şey giriş noktasına geçtiğinden, görüntülerinizden çok hoş bir davranış yaşayabilirsiniz. @Jiri örneği iyi, bir görüntünün "ikili" olarak nasıl kullanılacağını gösterir. Giriş noktası ["/bin/cat"]olarak kullandıktan sonra bunu docker run img /etc/passwdyaparsanız /etc/passwd, komut alırsınız ve giriş noktasına iletilir, böylece sonuç sonucu yürütme basittir /bin/cat /etc/passwd.

Başka bir örnek, giriş noktası olarak herhangi bir klibe sahip olmak olacaktır. Eğer bir Redis imaja sahip Örneğin, yerine çalışan docker run redisimg redis -H something -u toto get key, sadece olabilir ENTRYPOINT ["redis", "-H", "something", "-u", "toto"]ve daha sonra aynı sonuç için böyle çalıştırın: docker run redisimg get key.


3
Bir şey değil. ENTRYPOINT çalışma zamanında bir meta veri ayarlayabilir (ancak geçersiz kılınabilir). zamanında yapmak, burada olacak.
creack

8
Varsayılan olarak ENTRYPOINT; bir kabuğun kullanılıp kullanılmayacağı, CMDkomutun kullanılan biçimine bağlıdır ( docs.docker.com/engine/reference/builder/#cmd ).
Blaisorblade

19
Bunun için teşekkürler, tarihsel bağlam, neyin geçersiz kılındığı ve neyin eklenmiş olduğu gibi görünen gizemli kuralları hatırlamakta zorlandığım için çok yardımcı oluyor. sadece olayları ve senaryoları listelemeyin :-)
ashirley

84
Bu harika bir cevap. Docker belgelerinin bunu CMDvs adında bir bölüm altına eklemesi gerektiğini düşünüyorum ENTRYPOINT.
Tarık

5
@Webman Hayır. Bunlar iki farklı talimattır. Her ikisi de mevcutsa, CMD ENTRYPOINT'in parametreleri olarak kabul edilir.
Light.G

628

ENTRYPOINTBelirtir konteyner başladığında hep idam edilecek bir komut.

CMDBeslenecektir belirtir argümanlar ENTRYPOINT.

Belirli bir komuta adanmış bir görüntü oluşturmak istiyorsanız, ENTRYPOINT ["/path/dedicated_command"]

Aksi takdirde, genel amaçlı bir görüntü oluşturmak istiyorsanız, ENTRYPOINTbelirtilmemiş CMD ["/path/dedicated_command"]olarak bırakabilirsiniz ve argümanları sağlayarak ayarı geçersiz kılabileceğiniz için kullanabilirsiniz docker run.

Örneğin, Dockerfile dosyanız:

FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]

Görüntüyü herhangi bir argüman olmadan çalıştırmak localhost'a ping atacaktır:

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.088 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.088/0.091/0.096/0.000 ms

Şimdi, görüntüyü bir argümanla çalıştırmak, argümana ping atacaktır:

$ docker run -it test google.com
PING google.com (173.194.45.70): 48 data bytes
56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms
56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms
56 bytes from 173.194.45.70: icmp_seq=4 ttl=55 time=46.379 ms
^C--- google.com ping statistics ---
5 packets transmitted, 3 packets received, 40% packet loss
round-trip min/avg/max/stddev = 30.327/36.430/46.379/7.095 ms

Karşılaştırma için Dockerfile dosyanız:

FROM debian:wheezy
CMD ["/bin/ping", "localhost"]

Görüntüyü herhangi bir argüman olmadan çalıştırmak localhost'a ping atacaktır:

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.076/0.084/0.090/0.000 ms

Ancak görüntüyü bir argümanla çalıştırmak argümanı çalıştırır:

docker run -it test bash
root@e8bb7249b843:/#

Daha fazla ayrıntı için Brian DeHamer'ın bu makalesine bakın: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/


219
The ENTRYPOINT specifies a command that will always be executed when the container starts. The CMD specifies arguments that will be fed to the ENTRYPOINT.nokta iyi bir özettir.
Jingguo Yao

1
ENTRYPOINT, --entrypoint bayrağı kullanılarak da geçersiz kılınabilir. örneğin docker run -it --entrypoint bash testi
seenimurugan

2
Örneklerini beğendim, gerçekten yararlı!
Chau Giang

2
@Jingguo Yao: CMD - CMD ["nginx", "- g", "daemon", "off"] gibi bir komut içeriyorsa ne olur? Zincirleme olur mu?
KMC

@KMC CMD, ENTRYPOINT'in varsayılan bağımsız değişkenidir, görüntüyü çalıştırırken yeni bir argüman ileterek geçersiz kılarsınız.
MGP

237

Docker belgelerine göre ,

Hem CMD hem de ENTRYPOINT talimatları, bir kap çalıştırılırken hangi komutun yürütüleceğini tanımlar. İşbirliğini tanımlayan birkaç kural vardır.

  1. Dockerfile komutlarından en az birini CMDveya ENTRYPOINTkomutları belirtmelidir .
  2. ENTRYPOINT kap yürütülebilir bir dosya olarak kullanılırken tanımlanmalıdır.
  3. CMDbir ENTRYPOINTkomut için varsayılan bağımsız değişkenleri tanımlamanın veya bir kapsayıcıda geçici bir komutu yürütmenin bir yolu olarak kullanılmalıdır .
  4. CMD kapsayıcı alternatif bağımsız değişkenlerle çalıştırılırken geçersiz kılınır.

Aşağıdaki tablolarda farklı ENTRYPOINT/ CMDkombinasyonlar için hangi komutun yürütüldüğü gösterilmektedir :

- No ENTRYPOINT

╔════════════════════════════╦═════════════════════════════╗
║ No CMD                     ║ error, not allowed          ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ exec_cmd p1_cmd             ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ p1_cmd p2_cmd               ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_cmd p1_cmd  ║
╚════════════════════════════╩═════════════════════════════╝

- ENTRYPOINT exec_entry p1_entry

╔════════════════════════════╦══════════════════════════════════╗
║ No CMD                     ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_entry p1_entry   ║
╚════════════════════════════╩══════════════════════════════════╝

- ENTRYPOINT [“exec_entry”, “p1_entry”]

╔════════════════════════════╦═════════════════════════════════════════════════╗
║ No CMD                     ║ exec_entry p1_entry                             ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ exec_entry p1_entry exec_cmd p1_cmd             ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ exec_entry p1_entry p1_cmd p2_cmd               ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd  ║
╚════════════════════════════╩═════════════════════════════════════════════════╝

Px_cmd ve exec_entry nedir? Aynı yürütme çizgisinde olduklarında ne anlama geliyor? Birbirlerine argüman olarak geçtiler mi? Ne zaman /bin/sh -cdahil olur?
Danielo515

1
@ Danielo515 Hem 'px_cmd' hem de 'exec_entry' buradaki kukla dizelerdir. /bin/sh -cCMD'nin yürütülebilir sözdiziminde (liste sözdizimi değil) yazılırken CMD'ye önek olarak ekleneceğini fark edebilirsiniz .
Light.G

1
@royki Kullanıcı docker çalıştırması için bağımsız değişkenler belirtirse, CMD'de belirtilen varsayılan değeri geçersiz kılar.
donrondadon

2
ENTRYPOINT exec_entry p1_entyanlış açıklandı. Kabuk formu herhangi bir CMD'nin veya çalıştırma komut satırı bağımsız değişkenlerinin kullanılmasını önler - docs.docker.com/engine/reference/builder/#entrypoint
Mariusz Miesiak

1
@MariuszMiesiak şimdi güncellendi. Geri bildiriminiz için teşekkürler.
Rafaf Tahsin

170

Evet, bu iyi bir soru. Henüz tam olarak anlamıyorum ama:

Bunun ENTRYPOINTyürütülen ikili dosya olduğunu anlıyorum . Giriş noktasını --entrypoint = "" ile geçersiz kılabilirsiniz.

docker run -t -i --entrypoint="/bin/bash" ubuntu

CMD, kapsayıcı için varsayılan bağımsız değişkendir. Giriş noktası olmadan, varsayılan argüman yürütülen komuttur. Girdi noktası ile cmd argüman olarak girdi noktasına geçirilir. Bir komutu giriş noktasıyla taklit edebilirsiniz.

# no entrypoint
docker run ubuntu /bin/cat /etc/passwd

# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd

Yani, ana avantajı giriş noktası ile kabınıza argüman (cmd) iletebilmenizdir. Bunu yapmak için her ikisini de kullanmanız gerekir:

# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]

ve

docker build -t=cat .

o zaman kullanabilirsiniz:

docker run cat /etc/passwd
#              ^^^^^^^^^^^
#                   CMD
#          ^^^      
#          image (tag)- using the default ENTRYPOINT

@Blauhirn Sizin durumunuzda, liste sözdiziminde CMD'ye bağımsız değişkenler eklemeniz ve ayırdığınız giriş noktasının CMD'deki bağımsız değişkenlerinizi ayrıştırabildiğinden emin olmanız gerekir. Genellikle, giriş noktasına bir '-h' argümanı eklerim. Sonra docker run image_name -hbu görüntü hakkında bazı yardım bilgilerini göstermek için yürütmek olabilir .
Light.G

1
Bu en basit ve net cevap.
Eric Wang

44

Sezgiye göre CMD ve ENTRYPOINT arasındaki fark :

  • ENTRYPOINT: kapsayıcı başlatıldığında çalıştırılacak komut.
  • CMD: kapsayıcı başladığında çalıştırılacak komut veya belirtilmişse ENTRYPOINT değişkenleri.

Evet, karışıyor.

Docker çalıştırmasını çalıştırırken bunlardan herhangi birini geçersiz kılabilirsiniz.

CMD ve ENTRYPOINT arasındaki fark örneği :

docker run -it --rm yourcontainer /bin/bash            <-- /bin/bash overrides CMD
                                                       <-- /bin/bash does not override ENTRYPOINT
docker run -it --rm --entrypoint ls yourcontainer      <-- overrides ENTRYPOINT with ls
docker run -it --rm --entrypoint ls yourcontainer  -la  <-- overrides ENTRYPOINT with ls and overrides CMD with -la

Arasındaki fark hakkında daha fazla CMDve ENTRYPOINT:

İçin Argüman docker rungibi / bin / bash geçersiz kılar herhangi CMD komutu biz Dockerfile yazdı.

ENTRYPOINT gibi normal komutlarla çalışma zamanında geçersiz kılınamaz docker run [args]. argsUç bölgesinde docker run [args]giriş noktası için bağımsız değişken olarak temin edilmiştir. Bu şekilde containernormal bir ikili gibi bir tane oluşturabiliriz ls.

Bu nedenle CMD, ENTRYPOINT için varsayılan parametreler olarak işlev görebilir ve ardından CMD değişkenlerini [args] 'den geçersiz kılabiliriz.

ENTRYPOINT ile geçersiz kılınabilir --entrypoint.


38

Kısaca:

  • CMD, docker konteyneri çalıştığında komut satırından üzerine yazılabilen varsayılan komutu ve / veya parametreleri ayarlar.
  • ENTRYPOINT komutu ve parametrelerinin üzerine komut satırından yazılmaz. Bunun yerine, tüm komut satırı bağımsız değişkenleri ENTRYPOINT parametrelerinden sonra eklenir.

Daha fazla ayrıntıya ihtiyacınız varsa veya örnekte fark görmek istiyorsanız, CMD ve ENTRYPOINT'i birçok örnekle kapsamlı bir şekilde karşılaştıran bir blog yazısı var - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/


21

Cevabımı daha iyi anlamanıza yardımcı olabilecek bir örnek 1 olarak ekleyeceğim .

Diyelim ki başladığında her zaman bir uyku komutu çalıştıracak bir görüntü oluşturmak istiyoruz . Kendi imajımızı oluşturacağız ve yeni bir komut belirleyeceğiz:

FROM ubuntu
CMD sleep 10

Şimdi görüntüyü oluşturuyoruz:

docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits

Saniye sayısını değiştirmek istersek ne olur? DockerfileDeğer burada kodlanmış olarak değiştirilmeli veya farklı bir değer girilerek komutu geçersiz kılmalıyız:

docker run custom_sleep sleep 20

Bu işe yarar olsa da, gereksiz bir "uyku" komutuna sahip olduğumuz için iyi bir çözüm değildir (kabın amacı uyumaktır , bu yüzden sleepkomutu açıkça belirtmek zorunda kalmak iyi bir uygulama değildir).

Şimdi ENTRYPOINTtalimatı kullanmayı deneyelim :

FROM ubuntu
ENTRYPOINT sleep

Bu talimat , kapsayıcı başlatıldığında çalıştırılacak programı belirtir .

Şimdi koşabiliriz:

docker run custom_sleep 20

Varsayılan değer ne olacak? Doğru tahmin ettin:

FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]

ENTRYPOINTÇalıştırılacak program ve kaba iletilen değer buna eklenir.

ENTRYPOINTBir belirterek geçersiz kılınmış olabilir --entrypointkullanmak istediğiniz yeni giriş noktasından ardından bayrağı.

Benim değil, bir zamanlar bu örneği sağlayan bir öğretici izledim


1
Öğreticiye bir link: youtu.be/OYbEWUbmk90 . Gelecekteki kullanıcılar için yararlı olabilir.
ChiPlusPlus


7

İçinde GirişNoktası fonksiyonu üzerine yorumlar kodu

// ENTRYPOINT / usr / sbin / nginx.

// (us-sh olarak varsayılan olan) giriş noktasını / usr / sbin / nginx olarak ayarlayın.

// CMD'yi / usr / sbin / nginx değişkenine kabul eder.

Belgelerden başka bir referans

ENTRYPOINT komut biçimini, oldukça kararlı varsayılan komutları ve bağımsız değişkenleri ayarlamak için kullanabilir ve ardından CMD'yi kullanarak değiştirilmesi daha olası olan varsayılanları ayarlayabilirsiniz.

Misal:

FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]

Yapı : sudo docker yapı -t ent_cmd.

CMD arguments are easy to override.

NO argument (sudo docker -it ent_cmd)                :  ping localhost 
argument    (sudo docker run -it ent_cmd google.com) :  ping google.com

.

To override EntryPoint argument, you need to supply entrypoint
sudo docker run -it --entrypoint="/bin/bash" ent_cmdd

ps: EntryPoint'in varlığında CMD, EntryPoint'e beslenecek bağımsız değişkenler tutar. EntryPoint'in yokluğunda CMD çalıştırılacak komut olacaktır.


3

CMDDockerfiledosya içinde belirtilen komut komut ile geçersiz kılınamaz docker runiken ENTRYPOINTolamaz.


4
docker run --helpkomut aksi diyor:--entrypoint string Overwrite the default ENTRYPOINT of the image
iomv

3

Tüm cevapları okudum ve ilk bakışta aşağıdaki gibi daha iyi anlaşılması için özetlemek istiyorum:

İlk olarak, kapta yürütülen tüm komut iki bölüm içerir: komut ve bağımsız değişkenler

  • ENTRYPOINT , kapsayıcı başlatıldığında çağrılan yürütülebilir dosyayı tanımlar (komut için)

  • CMD , ENTRYPOINT öğesine aktarılan bağımsız değişkenleri belirtir (bağımsız değişkenler için)

In Kubernetes In Action kitabında bu konuda önemli bir not etmektedir. (Bölüm 7)

Kullanmak rağmen CMD görüntü çalıştırıldığında yürütmek istediğiniz komutu belirtmek için talimat, doğru yolu aracılığıyla yapmaktır entrypoint talimat ve sadece belirtmek CMD varsayılan argümanlar tanımlamak istiyorsanız.

Harika bir açıklama için bu makaleyi basit bir şekilde de okuyabilirsiniz


2

CMD:

  • CMD ["executable","param1","param2"]: ["executable","param1","param2"]ilk işlemdir.
  • CMD command param1 param2: /bin/sh -c CMD command param1 param2ilk işlemdir. CMD command param1 param2ilk süreçten çatallanır.
  • CMD ["param1","param2"]: Bu form, için varsayılan bağımsız değişkenler sağlamak için kullanılır ENTRYPOINT.

ENTRYPOINT (Aşağıdaki liste, CMD ve ENTRYPOINT'in birlikte kullanıldığı durumu dikkate almaz):

  • ENTRYPOINT ["executable", "param1", "param2"]: ["executable", "param1", "param2"]ilk işlemdir.
  • ENTRYPOINT command param1 param2: /bin/sh -c command param1 param2ilk işlemdir. command param1 param2ilk süreçten çatallanır.

Gibi creack dedi CMD ilk geliştirildi. Daha sonra ENTRYPOINT daha fazla özelleştirme için geliştirildi. Birlikte tasarlanmadığından, CMD ve ENTRYPOINT arasında genellikle insanları şaşırtan bazı işlevler çakışıyor.


2

Çoğu insan burada mükemmel bir şekilde açıklıyor, bu yüzden tüm cevapları tekrarlamayacağım. Ancak iyi bir his elde etmek için kaptaki süreçlere bakarak kendiniz test etmenizi öneririm.

Formun küçük bir Docker dosyası oluşturun:

FROM ubuntu:latest
CMD /bin/bash

Oluşturun, ile docker run -it theimageçalıştırın ps -eo ppid,pid,argsve kapta çalıştırın . Bu çıkışı kullanırken ps'den aldığınız çıkışla karşılaştırın:

  • docker run -it theimage bash
  • Görüntüyü yeniden oluşturma ancak ENTRYPOINT /bin/bashher iki şekilde
  • kullanma CMD ["/bin/bash"]
  • ...

Bu şekilde tüm olası yöntemler arasındaki farkları kendiniz kolayca göreceksiniz.


0

Dockerfile en iyi uygulamalarının resmi dokümantasyonu, farklılıkları açıklayan harika bir iş çıkarır. Dockerfile en iyi uygulamaları

CMD:

CMD komutu, herhangi bir argümanla birlikte görüntünüzün içerdiği yazılımı çalıştırmak için kullanılmalıdır. CMD neredeyse her zaman şeklinde kullanılmalıdır CMD ["executable", "param1", "param2"…]. Dolayısıyla, görüntü Apache ve Rails gibi bir hizmet içinse, böyle bir şey çalıştırırsınız CMD ["apache2","-DFOREGROUND"]. Aslında, talimatın bu formu herhangi bir servis tabanlı görüntü için önerilir.

GİRİŞ NOKTASI:

ENTRYPOINT için en iyi kullanım, görüntünün ana komutunu ayarlamaktır, bu görüntünün bu komutmuş gibi çalıştırılmasına izin verir (ve sonra CMD'yi varsayılan bayraklar olarak kullanır).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.