Di Dockerfiles ada dua perintah yang terlihat mirip dengan saya: CMD
dan ENTRYPOINT
. Tapi saya rasa itu ada (halus?) perbedaan antara mereka - jika tidak maka akan tidak masuk akal untuk memiliki dua perintah untuk hal yang sama.
Dokumentasi serikat untuk CMD
tujuan utama dari CMD adalah untuk memberikan default untuk melaksanakan wadah.
dan untuk ENTRYPOINT
:
Sebuah ENTRYPOINT membantu anda untuk mengkonfigurasi sebuah wadah yang dapat anda jalankan sebagai executable.
Jadi, apa yang's perbedaan antara kedua perintah?
Docker memiliki default entrypoint yang merupakan /bin/sh -c
tetapi tidak memiliki perintah default.
Ketika anda menjalankan docker seperti ini:
docker run-i-t ubuntu bash
yang entrypoint adalah default /bin/sh -c
, gambar ubuntu
dan perintah adalah bash
.
Perintah ini dijalankan melalui entrypoint. yaitu, sebenarnya hal yang akan dieksekusi adalah /bin/sh -c bash
. Hal ini memungkinkan Docker untuk melaksanakan BERLARI
cepat dengan mengandalkan shell's parser.
Kemudian, orang-orang diminta untuk dapat menyesuaikan ini, jadi ENTRYPOINT
dan --entrypoint
diperkenalkan.
Semuanya setelah ubuntu
dalam contoh di atas adalah perintah dan diteruskan ke entrypoint. Ketika menggunakan CMD
instruksi, itu adalah persis seperti jika anda melakukan docker run-i-t ubuntu <cmd>
. <cmd>
akan menjadi parameter entrypoint.
Anda juga akan mendapatkan hasil yang sama jika anda bukan tipe perintah ini docker run-i-t ubuntu
. Anda masih akan memulai bash shell dalam wadah karena ubuntu Dockerfile ditentukan default CMD: CMD ["bash"]
Karena semuanya diteruskan ke entrypoint, anda dapat memiliki waktu yang sangat baik perilaku dari gambar anda. @Jiri contoh yang baik, ini menunjukkan bagaimana untuk menggunakan gambar sebagai "biner". Ketika menggunakan ["/bin/kucing"]
sebagai entrypoint dan kemudian melakukan docker menjalankan img /etc/passwd
, anda mendapatkan itu, /etc/passwd
adalah perintah dan diteruskan ke entrypoint sehingga hasil akhir eksekusi hanya /bin/cat /etc/passwd
.
Contoh lain akan memiliki cli sebagai entrypoint. Misalnya, jika anda memiliki redis gambar, bukan berjalan docker menjalankan redisimg redis -Jam sesuatu -u toto mendapatkan kunci
, anda hanya dapat memiliki ENTRYPOINT ["redis", " H", "sesuatu", "-u", "toto"]
dan kemudian jalankan seperti ini untuk hasil yang sama: docker menjalankan redisimg mendapatkan kunci
.
The ENTRYPOINT
menentukan perintah yang akan selalu dijalankan ketika wadah dimulai.
The CMD
menentukan argumen yang akan diumpankan ke ENTRYPOINT
.
Jika anda ingin membuat gambar yang didedikasikan untuk perintah tertentu anda akan menggunakan ENTRYPOINT ["/path/dedicated_command"]
Sebaliknya, jika anda ingin membuat gambar untuk tujuan umum, anda dapat meninggalkan ENTRYPOINT
yang tidak ditentukan dan menggunakan CMD ["/path/dedicated_command"]
seperti yang anda akan dapat menimpa pengaturan dengan menyediakan argumen untuk docker run
.
Misalnya, jika anda Dockerfile adalah:
FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]
Menjalankan gambar tanpa argumen akan melakukan 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
Sekarang, menjalankan gambar dengan argumen akan ping argumen:
$ 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
Sebagai perbandingan, jika anda Dockerfile adalah:
FROM debian:wheezy
CMD ["/bin/ping", "localhost"]
Menjalankan gambar tanpa argumen akan melakukan 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
Tapi menjalankan gambar dengan argumen akan menjalankan argumen:
docker run -it test bash
root@e8bb7249b843:/#
Lihat artikel ini dari Brian DeHamer untuk rincian lebih lanjut: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/
Menurut docker docs,
Kedua CMD dan ENTRYPOINT instruksi mendefinisikan apa perintah akan dieksekusi ketika menjalankan sebuah wadah. Ada beberapa aturan yang menggambarkan mereka kerjasama.
- Dockerfile harus menentukan setidaknya satu dari
CMD
atauENTRYPOINT
perintah.ENTRYPOINT
harus didefinisikan bila menggunakan kontainer sebagai executable.CMD
harus digunakan sebagai cara untuk mendefinisikan default argumen untuk sebuahENTRYPOINT
atau perintah untuk mengeksekusi suatu perintah ad-hoc di wadah.CMD
akan diganti ketika menjalankan wadah dengan alternatif argumen.
Tabel di bawah ini menunjukkan apa perintah dijalankan untuk berbeda ENTRYPOINT
/ CMD
kombinasi:
-- Ada 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 ║
╚════════════════════════════╩═════════════════════════════════════════════════╝
Ya, itu adalah pertanyaan yang bagus. Saya don't memahami hal ini sepenuhnya, tapi:
Saya memahami bahwa ENTRYPOINT
adalah biner yang sedang dijalankan. Anda dapat overide entrypoint oleh-entrypoint="".
docker run -t -i --entrypoint="/bin/bash" ubuntu
CMD adalah default argumen untuk wadah. Tanpa entrypoint, default argumen adalah perintah yang dieksekusi. Dengan entrypoint, cmd diteruskan ke entrypoint sebagai argumen. Anda bisa meniru perintah dengan entrypoint.
# no entrypoint
docker run ubuntu /bin/cat /etc/passwd
# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd
Jadi, keuntungan utama adalah bahwa dengan entrypoint anda dapat melewati argumen (cmd) untuk kontainer anda. Untuk mencapai hal ini, anda perlu menggunakan keduanya:
# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]
dan
docker build -t=cat .
kemudian anda dapat menggunakan:
docker run cat /etc/passwd
# ^^^^^^^^^^^
# CMD
# ^^^
# image (tag)- using the default ENTRYPOINT
Perbedaan antara CMD dan ENTRYPOINT dengan intuisi:
Ya, itu's mencampur.
Anda dapat mengganti salah satu dari mereka ketika menjalankan docker berjalan.
Perbedaan antara CMD dan ENTRYPOINT contoh:
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
Lebih lanjut tentang perbedaan antara CMD
dan ENTRYPOINT
:
Argumen untuk docker run
seperti /bin/bash menimpa setiap perintah CMD kita menulis di Dockerfile.
ENTRYPOINT tidak dapat diganti pada waktu berjalan dengan normal perintah seperti docker menjalankan [argumen]
. The args
di akhir docker menjalankan [argumen]
yang diberikan sebagai argumen ke ENTRYPOINT. Dengan cara ini kita dapat membuat sebuah wadah
yang seperti biner normal seperti ls
.
Jadi CMD dapat bertindak sebagai default parameter untuk ENTRYPOINT dan kemudian kita dapat menimpa CMD args dari [argumen].
ENTRYPOINT dapat diganti dengan --entrypoint
.
Singkatnya:
Jika anda memerlukan informasi lebih lanjut atau ingin melihat perbedaan pada contoh, ada sebuah posting blog yang komprehensif membandingkan CMD dan ENTRYPOINT dengan banyak contoh - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/
Jawaban yang diterima adalah yang hebat dalam menjelaskan sejarah. Saya menemukan tabel ini menjelaskan dengan sangat baik dari resmi doc di 'cara CMD dan ENTRYPOINT berinteraksi':
I'll menambahkan jawaban saya sebagai contoh1 yang mungkin bisa membantu anda lebih memahami perbedaan.
Let's misalkan kita ingin membuat gambar yang akan selalu menjalankan tidur perintah ketika itu dimulai. Kami'akan membuat gambar kita sendiri dan menentukan perintah baru:
bash DARI ubuntu CMD tidur 10
Sekarang, kita membangun citra:
docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits
Bagaimana jika kita ingin mengubah jumlah detik? Kami akan harus mengubah Dockerfile
sebagai nilai hardcoded ada, atau mengganti perintah dengan menyediakan satu yang berbeda:
docker run custom_sleep sleep 20
Sementara ini bekerja, it's bukan solusi yang baik, seperti yang telah kita berlebihan "tidur" perintah (wadah's tujuan adalah untuk tidur, jadi harus secara eksplisit menentukan tidur
perintah ini tidak praktek yang baik).
Sekarang mari's mencoba menggunakan ENTRYPOINT
instruksi:
bash DARI ubuntu ENTRYPOINT tidur
Instruksi ini menentukan program yang akan dijalankan ketika wadah dimulai.
Sekarang kita dapat menjalankan:
bash docker menjalankan custom_sleep 20
Bagaimana dengan nilai default? Nah, anda menebak dengan benar:
bash DARI ubuntu ENTRYPOINT ["tidur"] CMD ["10"]
The ENTRYPOINT
adalah program yang akan dijalankan, dan nilai yang diteruskan ke wadah yang akan ditambahkan ke dalamnya.
The ENTRYPOINT
dapat diganti dengan menentukan sebuah --entrypoint
bendera, diikuti oleh new entry point yang ingin anda gunakan.
Bukan milikku, saya pernah menyaksikan sebuah tutorial yang disediakan contoh ini
Komentar pada EntryPoint fungsi di code
// ENTRYPOINT /usr/sbin/nginx.
// Mengatur entrypoint (default sh -c) ke /usr/sbin/nginx.
// Akan menerima CMD sebagai argumen ke /usr/sbin/nginx.
Referensi lain dari dokumen
Anda dapat menggunakan exec bentuk ENTRYPOINT untuk mengatur cukup stabil default perintah dan argumen dan kemudian menggunakan CMD untuk menetapkan tambahan default yang lebih mungkin untuk diubah.
Contoh:
FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]
Membangun: sudo docker membangun -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: Di hadapan EntryPoint, CMD akan mengadakan argumen untuk diumpankan ke EntryPoint. Dalam ketiadaan EntryPoint, CMD akan menjadi perintah yang akan dijalankan.
CMD:
CMD ["eksekusi","param1","param2"]
: ["eksekusi","param1","param2"]
adalah proses pertama.CMD param1 param2
: /bin/sh -c CMD param1 param2
adalah proses pertama. CMD param1 param2
bercabang dari proses pertama.CMD ["param1","param2"]
: formulir Ini digunakan untuk memberikan argumen default untuk ENTRYPOINT
.ENTRYPOINT (daftar berikut tidak mempertimbangkan kasus di mana CMD dan ENTRYPOINT digunakan bersama-sama):
ENTRYPOINT ["eksekusi", "param1", "param2"]
: ["eksekusi", "param1", "param2"]
adalah proses pertama.ENTRYPOINT perintah param1 param2
: /bin/sh -c perintah param1 param2
adalah proses pertama. perintah param1 param2
bercabang dari proses pertama.Sebagai creack mengatakan, CMD dikembangkan terlebih dahulu. Kemudian ENTRYPOINT dikembangkan untuk kustomisasi lebih. Karena mereka tidak dirancang bersama-sama, ada beberapa fungsi yang tumpang tindih antara CMD dan ENTRYPOINT, yang sering membingungkan orang.
Kebanyakan orang menjelaskannya di sini, jadi saya tidak't ulangi semua jawaban. Tapi untuk mendapatkan perasaan yang baik saya akan menyarankan pengujian itu sendiri dengan melihat proses-proses dalam wadah.
Membuat kecil Dockerfile dalam bentuk:
FROM ubuntu:latest
CMD /bin/bash
Membangun itu, jalankan itu dengan docker run-itu theimage
dan berlari ps -eo ppid,pid,args
dalam wadah.
Bandingkan output untuk output yang anda terima dari ps ketika menggunakan:
docker run-itu theimage bash
ENTRYPOINT /bin/bash
dan berjalan di kedua caraCMD ["/bin/bash"]
Dengan cara ini anda akan dengan mudah melihat perbedaan antara semua metode yang mungkin untuk diri sendiri.