În Dockerfiles există două comenzi care să arate similar cu mine: CMD " și " ENTRYPOINT
. Dar cred că există un (subtil?) diferența dintre ele - altfel nu ar face nici un sens pentru a avea două comenzi pentru acelasi lucru.
Documentația membre pentru "CMD"
scopul principal al unui CMD este de a oferi valori implicite pentru un recipient de executare.
și pentru ENTRYPOINT`:
O ENTRYPOINT vă ajută să configurați un recipient care poate rula ca un executabil.
Deci, ceea ce's, diferența între cele două comenzi?
Docker are un default entrypoint care este /bin/sh -c
ci nu avea o comandă implicit.
Când executați docker astfel:
docker fugi -i-t ubuntu bash
la entrypoint este implicit /bin/sh -c
, imaginea este ubuntu
iar comanda este bash
.
La comanda se execută prin obtinerea a apărut. de exemplu, lucru real, care este executat este /bin/sh -c bash
. Acest lucru a permis Docker să pună în aplicare " RUN " rapid, bazându-se pe shell's parser.
Mai târziu, oamenii au cerut să fie capabil de a personaliza acest lucru, așa ENTRYPOINT " și " --entrypoint` au fost introduse.
Totul după ubuntu
în exemplul de mai sus este comanda și este trecut la obtinerea a apărut. Atunci când se utilizează "CMD", instrucțiuni, este exact ca și cum ați face docker fugi -i-t ubuntu <cmd>
. <cmd>
va fi parametrul de obtinerea a apărut.
De asemenea, veți obține același rezultat dacă, în loc să introduceți această comandă docker fugi -i-t ubuntu
. Veți începe încă un bash shell în container pentru a ubuntu Dockerfile se specifică o valoare implicită CMD: CMD ["bash"]
Ca tot ce este trecut la obtinerea a apărut, puteți avea un comportament frumos din imagini. @Jiri exemplu este bună, ea arată cum să utilizați o imagine ca un "binar". Atunci când se utilizează ["/bin/cat"]
ca entrypoint și apoi face docker rula img /etc/passwd, tu a lua it,
/etc/passwdeste comanda și este trecut la entrypoint astfel încât rezultatul final de execuție este pur și simplu
/bin/cat /etc/passwd`.
Un alt exemplu ar fi să aibă nici o cli ca obtinerea a apărut. De exemplu, dacă aveți un redis imagine, în loc să docker rula redisimg redis -H ceva -u toto obține cheia, puteți pur și simplu au ENTRYPOINT ["redis", " H", "ceva", " u", "toto"] și apoi executați pentru același rezultat:
docker rula redisimg obține cheia`.
Anii ENTRYPOINT
specifică o comandă care va fi întotdeauna executate atunci când începe container.
La "CMD", precizează argumentele care va fi alimentat la ENTRYPOINT
.
Dacă doriți să faceți o imagine dedicat o anumită comandă va utiliza ENTRYPOINT ["/calea/dedicated_command"]
În caz contrar, dacă doriți să faceți o imagine pentru uz general, puteți lăsa ENTRYPOINTnespecificate și de a folosi
CMD ["/calea/dedicated_command"]ca va fi capabil să suprascrie setarea prin furnizarea de argumente pentru a
docker run`.
De exemplu, dacă Dockerfile este:
FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]
Rulează imaginea fără nici un argument va ping localhost:
$ 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
Acum, care rulează imaginea cu un argument va ping argument:
$ 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
Pentru comparație, dacă Dockerfile este:
FROM debian:wheezy
CMD ["/bin/ping", "localhost"]
Rulează imaginea fără nici un argument va ping localhost:
$ 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
Dar care rulează imaginea cu un argument va rula argument:
docker run -it test bash
root@e8bb7249b843:/#
A se vedea acest articol de la Brian DeHamer pentru mai multe detalii: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/
Potrivit docker docs,
Ambele CMD și ENTRYPOINT instrucțiuni definesc ce comanda a executat atunci când rulează un recipient. Există câteva reguli care descriu lor cooperare.
- Dockerfile ar trebui să precizeze cel puțin unul din CMD " sau " ENTRYPOINT` comenzi.
ENTRYPOINT
ar trebui să fie definite atunci când se utilizează containere ca un executabil.- "CMD", ar trebui să fie folosit ca o modalitate de definire default argumente pentru o
ENTRYPOINT
comanda sau pentru a executa o comanda ad-hoc într-un recipient.- "CMD", va fi anulată atunci când rulează recipientul cu alternative de argumente.
Tabelele de mai jos prezinta * ce este executat comanda pentru diferite ENTRYPOINT
/ " CMD " combinații**:
-- Nu 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 ║
╚════════════════════════════╩═════════════════════════════════════════════════╝
Da, asta este o întrebare bună. Eu nu't-l înțeleagă pe deplin încă, dar:
Am înțeles că ENTRYPOINT
este binar care este executat. Puteți overide entrypoint de ... entrypoint="".
docker run -t -i --entrypoint="/bin/bash" ubuntu
CMD este implicit argument pentru container. Fără entrypoint, default argument este comanda care este executat. Cu entrypoint, cmd este trecut la obtinerea a apărut ca argument. Vă pot emula o comandă cu obtinerea a apărut.
# no entrypoint
docker run ubuntu /bin/cat /etc/passwd
# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd
Deci, principalul avantaj este că, cu entrypoint puteți trece argumente (cmd) la containere. Pentru a realiza acest lucru, aveți nevoie pentru a utiliza ambele:
# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]
și
docker build -t=cat .
apoi, puteți utiliza:
docker run cat /etc/passwd
# ^^^^^^^^^^^
# CMD
# ^^^
# image (tag)- using the default ENTRYPOINT
Diferența dintre CMD și ENTRYPOINT de intuiție:
Da, l's amestecarea.
Puteți înlocui oricare dintre ele atunci când rulează docker rula.
Diferența dintre CMD și ENTRYPOINT de exemplu:
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
Mai multe despre diferența dintre " CMD " și ENTRYPOINT
:
Argument pentru docker run
precum /bin/bash suprascrie orice comanda CMD am scris în Dockerfile.
ENTRYPOINT nu poate fi suprascrisă în timpul rulării normale de comenzi, cum ar fi docher centrare [args]
. Anii args la sfârșitul lui
docher centrare [args] sunt furnizate ca argumente pentru obtinerea a apărut. În acest fel putem crea un "container", care este ca un normal binare, cum ar fi "ls".
Deci CMD poate acționa ca parametri implicite pentru obtinerea a apărut și apoi putem trece peste CMD args de [args].
ENTRYPOINT poate fi suprascrisă cu --entrypoint
.
Într-un cuvânt:
Dacă aveți nevoie de mai multe detalii sau ar dori să vadă diferența pe exemplu, există un post pe blog că cuprinzător compara CMD si obtinerea a apărut cu o mulțime de exemple - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/
Acceptat răspunsul este fabulos în explicarea istoriei. Am găsit acest tabel se explica foarte bine de oficial doc pe 'cum CMD și ENTRYPOINT interacționa':
Am'll a adăuga răspunsul meu ca un exemplu1 care ar putea ajuta să înțelegem mai bine diferența.
Las's presupunem că doriți să creați o imagine care va întotdeauna un somn de comandă atunci când începe. Am'll crea propria noastră imagine și specificați o noua comanda:
bash DE la ubuntu CMD dormi 10
Acum, vom construi imaginea:
docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits
Dacă vrem să schimbăm numărul de secunde? Ne-ar trebuie să se schimbe Dockerfile
ca valoarea este hardcoded acolo, sau anula comanda prin furnizarea de o alta:
docker run custom_sleep sleep 20
În timp ce acesta funcționează, l'nu e o soluție bună, deoarece avem un redundante "sleep" comandă (recipient's scop este de a somn, deci a fi nevoie să specificați în mod explicit "sleep" comanda nu este o bună practică).
Acum las's încercați să utilizați ENTRYPOINT
instrucțiuni:
bash DE la ubuntu ENTRYPOINT somn
Acest manual de instrucțiuni specifică program ce va fi rulat când începe container.
Acum putem rula:
bash docker rula custom_sleep 20
Ce zici de o valoare implicită? Ei bine, ai ghicit corect:
bash DE la ubuntu ENTRYPOINT ["sleep"] CMD ["și 10"]
Anii ENTRYPOINT
este un program care va fi rulat, și valoarea a trecut la container va fi adăugat la acesta.
Anii ENTRYPOINT
poate fi înlocuită prin specificarea unui --entrypoint
pavilion, urmat de noul punct de intrare doriți să o utilizați.
Nu a mea, am vazut un tutorial care a oferit acest exemplu
Comentarii pe EntryPoint funcție în code
// obtinerea a apărut /usr/sbin/nginx.
// Setați entrypoint (care implicit la sh -c) la /usr/sbin/nginx.
// Va accepta CMD ca argumente la /usr/sbin/nginx.
O altă referință la documentele
puteți folosi exec formă de ENTRYPOINT pentru a seta destul de stabil default comenzile și argumentele și de a folosi apoi CMD pentru a seta suplimentare implicite, care sunt mai susceptibile de a fi schimbat.
Exemplu:
FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]
Construi: sudo docker construi -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
p.s: În prezența EntryPoint, CMD va organiza argumente pentru a alimentat la obtinerea a apărut. În absența de EntryPoint, CMD va fi o comanda ce va fi rulat.
CMD:
CMD ["executabil","param1","param2"]
: ["executabil","param1","param2"]
este primul proces.CMD comanda param1 param2
: /bin/sh -c comanda CMD param1 param2
este primul proces. Comanda CMD param1 param2
este bifurcat de la primul proces.CMD ["param1","param2"]
: Acest formular este utilizat pentru a oferi default argumente pentru ENTRYPOINT`.ENTRYPOINT (lista De mai jos nu ia în considerare cazul în CMD și ENTRYPOINT sunt folosite împreună):
ENTRYPOINT ["executabil", "param1", "param2"]
: ["executabil", "param1", "param2"]
este primul proces.ENTRYPOINT comanda param1 param2
: /bin/sh -c comanda param1 param2
este primul proces. comanda param1 param2
este bifurcat de la primul proces.Ca creack a spus, CMD a fost dezvoltat în primul rând. Apoi ENTRYPOINT a fost dezvoltat pentru mai mult de personalizare. Deoarece acestea nu sunt proiectate împreună, există unele funcționalități suprapuneri între CMD și ENTRYPOINT, care de multe ori se confunda oameni.
Majoritatea oamenilor explica perfect aici, așa că am câștigat't repeta toate răspunsurile. Dar pentru a obține un sentiment bun mi-ar sugera de testare-te uitandu-te la procese în container.
A crea un mic Dockerfile de forma:
FROM ubuntu:latest
CMD /bin/bash
Construi, a alerga it cu docker este theimage
și a alerga ps -eo ppid,pid,args
în container.
Compara această ieșire la ieșire veți primi de la ps atunci când se utilizează:
docker este theimage bash
În acest fel, veți vedea cu ușurință diferențele dintre toate metodele posibile pentru tine.