SSD Nodes Learn 🎉 VPS kutoka $5.50/mwezi
Mwongozo Matt ConnorNa Matt Connor · Imeboreshwa 2026-08-13

Tofauti ya Docker Compose entrypoint na command

Jifunze jinsi ya kutumia entrypoint na command katika Docker Compose. Gundua kwa nini kuweka entrypoint hufuta CMD ya awali na jinsi ya kurekebisha makosa ya usanidi wa container.

Amri ya Docker Compose dhidi ya entrypoint, katika kanuni moja

Katika Docker Compose, entrypoint: huweka programu inayotekelezwa na command: huweka hoja (arguments) zinazopitishwa kwa programu hiyo. Mchakato wa container ni orodha ya entrypoint ikiwa na orodha ya command iliyoongezwa mwishoni mwake. Tabia nyingine zote kwenye ukurasa huu hutokana na sentensi hiyo moja.

Funguo hizo mbili hulingana na maelekezo mawili ya Dockerfile. entrypoint: hubadilisha ENTRYPOINT ya image. command: hubadilisha CMD ya image. Hizi si huru, na hapo ndipo watu hukwama: kuweka entrypoint: pia hufuta CMD ya image. Ufafanuzi wa Compose unasema hivi moja kwa moja. Ikiwa entrypoint si null, Compose hupuuza amri yoyote ya msingi (default command) kutoka kwenye image.

Soma kile ambacho image tayari imetangaza

Kabla ya kubadilisha usanidi wowote, angalia kile ambacho image inatoa.

docker image inspect --format '{{json .Config.Entrypoint}}' postgres:16
docker image inspect --format '{{json .Config.Cmd}}' postgres:16

Unapata ["docker-entrypoint.sh"] na ["postgres"], kwa hivyo container huendesha docker-entrypoint.sh postgres. Script hiyo hutengeneza saraka ya data wakati wa boot ya kwanza, husoma vigezo vya POSTGRES_*, hupunguza marupurupu hadi mtumiaji wa postgres, na hatimaye hutekeleza hoja (arguments) ilizopewa. Kujua ni nusu ipi unayotaka kubadilisha ndilo chaguo zima. Ili kupitisha flag kwenye database unabadilisha command:. Ukibadilisha entrypoint:, hakuna usanidi wowote kati ya hiyo utakaotekelezwa.

Mchanganyiko manne, yaliyoonyeshwa kwenye picha ndogo

Jenga image ambayo kazi yake pekee ni kuchapisha orodha ya argument iliyoanzishwa nayo.

FROM alpine:3.20
ENTRYPOINT ["/bin/echo", "ep"]
CMD ["cmd"]
docker build -t argdemo .
services:
  demo:
    image: argdemo

Tekeleza docker compose up baada ya kila marekebisho na usome mstari mmoja unaoingia kwenye log.

  • Hakuna key iliyowekwa. Mchakato ni /bin/echo ep cmd na log inaonyesha ep cmd.
  • command: ["cmd2"] pekee. Mchakato ni /bin/echo ep cmd2. Entrypoint haijaguswa na ni argument pekee zilizobadilika.
  • entrypoint: ["/bin/echo", "ep2"] pekee. Mchakato ni /bin/echo ep2 na log inaonyesha ep2. cmd kutoka kwenye image imepotea, na hakuna onyo lolote.
  • Keys zote mbili zimewekwa. Mchakato ni /bin/echo ep2 cmd2. Hii ndiyo hali pekee ambapo unadhibiti orodha nzima ya argument.

Kwa nini kuweka entrypoint hufuta CMD ya image

CMD ya image huandikwa kama orodha ya hoja chaguo-msingi kwa ajili ya ENTRYPOINT ya image hiyo. Badilisha entrypoint na hoja hizo sasa zitakuwa za programu ambayo haifanyi kazi tena, kwa hivyo Compose huziondoa badala ya kujenga mstari wa amri ambao mtunzi wa image hakukusudia uwepo. docker run --entrypoint hufanya kazi kwa njia hiyo hiyo, kwa hivyo huu ni mwenendo wa Docker badala ya kuwa sifa ya kipekee ya Compose.

Matokeo yake ni dhahiri. nginx:1.27 hutangaza ENTRYPOINT ["/docker-entrypoint.sh"] na CMD ["nginx", "-g", "daemon off;"]. Weka entrypoint: /custom-init.sh na hati yako itaanza na orodha tupu ya hoja. Hati inayomalizia na exec "$@" ya kawaida basi haina kitu cha ku-exec, kwa hivyo exec haifanyi chochote, hati hufika kwenye mstari wake wa mwisho, na container huzimika kwa code 0 bila ujumbe wowote wa hitilafu. Rudisha hoja hizo wewe mwenyewe:

services:
  web:
    image: nginx:1.27
    entrypoint: /custom-init.sh
    command: ["nginx", "-g", "daemon off;"]

Kanuni ya kuzingatia: wakati wowote unapoweka entrypoint:, amua command: inapaswa kuwa nini katika marekebisho hayo hayo.

Aina ya exec na aina ya shell, na jinsi Compose inavyotofautiana

Dockerfile inakubali sintaksia mbili. CMD ["nginx", "-g", "daemon off;"] ni aina ya exec: binary huendeshwa moja kwa moja, bila shell kuhusika. CMD nginx -g "daemon off;" ni aina ya shell: Docker huiandika upya kama /bin/sh -c 'nginx -g "daemon off;"', kwa hivyo shell huendesha kwanza na programu yako inakuwa mtoto wake (child process).

Compose haifuati kanuni hiyo, na jambo hili huwashangaza watu. Kamba ya maandishi (string) katika command: hugawanywa katika hoja (arguments) na kuendeshwa moja kwa moja, bila kanga ya /bin/sh -c. Rejeleo la Compose liko wazi kuhusu hili: sehemu ya command haiendeshwi ndani ya muktadha wa SHELL uliotajwa kwenye image, kwa hivyo ukihitaji vipengele vya shell lazima uanzishe shell mwenyewe.

Hiyo ndiyo sababu command: echo "hello $$HOSTNAME" huchapisha maandishi halisi ya hello $HOSTNAME. Hakuna shell iliyowahi kuona kamba hiyo, kwa hivyo hakuna kilichopanuliwa. Omba shell unapoihitaji:

services:
  demo:
    image: alpine:3.20
    command: /bin/sh -c 'echo "hello $$HOSTNAME"'

Ishara, PID 1, na amri safi ya docker compose down

docker compose stop na docker compose down hutuma SIGTERM kwa PID 1 ndani ya kila container, husubiri kwa stop_grace_period, kisha hutuma SIGKILL. Muda wa ziada wa kusubiri (grace period) ni sekunde 10.

PID 1 ni maalum katika Linux. Kernel haitumii hatua ya kawaida ya ishara kwa PID 1, kwa hivyo mchakato usio na SIGTERM handler hupuuza SIGTERM unapoendeshwa kama PID 1. Hukaa hapo kwa muda wote wa grace period kisha huuliwa ghafla, jambo linalokata muunganisho wowote ulio wazi au miamala isiyokamilika.

Shell iliyo mbele ya programu yako huongeza uwezekano huu, kwa sababu shell ndiyo PID 1 na shell nyingi hazisambazi ishara kwa mtoto (child process). Baadhi ya shell hujibadilisha na amri ya mwisho katika -c string, kwa hivyo wakati mwingine programu yako hufika PID 1 hata hivyo. Hilo hutegemea shell na string kamili, kwa hivyo usikisie. Isome:

docker compose exec -T web cat /proc/1/cmdline | tr '\0' ' '; echo

Ikiwa PID 1 inaonekana kama /bin/sh -c ... badala ya programu yako, kuna masuluhisho mawili. Tumia exec form kwenye image, au weka shell na ukabidhi mchakato kwa exec:

services:
  web:
    image: myapp:1.4
    command: /bin/sh -c 'exec myapp --config /etc/myapp.toml'

exec hubadilisha mchakato wa shell na programu yako badala ya kuunda mtoto, kwa hivyo programu yako hurithi PID 1 na kupokea ishara.

Baadhi ya programu huunda watoto na haziwatoi (reap), jambo linaloacha zombie processes, kwa sababu PID 1 pia ndiyo inayohusika na kutoa watoto. Compose ina swichi kwa ajili hiyo:

services:
  web:
    image: myapp:1.4
    init: true
    stop_grace_period: 30s

init: true huendesha mchakato mdogo wa init kama PID 1 ambao husambaza ishara kwa programu yako na kutoa watoto. stop_grace_period huipa shutdown ya polepole nafasi zaidi. Ikiwa programu yako inatarajia ishara tofauti, stop_signal: SIGQUIT hubadilisha kile Compose inachotuma. Soma kile image inachoomba tayari kwa docker image inspect --format '{{.Config.StopSignal}}' nginx:1.27.

Stack ambapo docker compose down huchukua sekunde kumi kila mara kwa kila huduma inakuambia kuwa hakuna kinachoshughulikia SIGTERM. Rekebisha hilo kabla ya kulaumu zana, na tazama tofauti kati ya docker compose down na stop kwa kile kila subcommand inachoondoa.

Mgawanyiko uleule wa exec-dhidi-ya-shell hujitokeza sehemu nyingine moja. Healthcheck iliyoandikwa kama test: ["CMD", "curl", "-f", "http://localhost/"] huendesha binary moja kwa moja, wakati test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"] huendesha kupitia shell ili || iwe na maana. Kuandika Compose healthchecks zinazofeli kwa usahihi inashughulikia sehemu iliyobaki ya uwanja huo.

Kuongeza flag kwenye image rasmi

Hili ndilo jambo ambalo wasomaji wengi wamekuja kutafuta. Unataka flag moja ya ziada kwenye postgres, na hupaswi kuvuruga script ya awali ya initialization.

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - pgdata:/var/lib/postgresql/data
    command: postgres -c max_connections=200 -c shared_buffers=256MB

volumes:
  pgdata:

Ni command: pekee iliyobadilika, kwa hivyo docker-entrypoint.sh bado inaendelea kufanya kazi na kutekeleza ulichokipa. Hakiki matokeo badala ya kudhani:

docker compose up -d db
docker compose exec -T db psql -U postgres -c 'show max_connections;'

Matokeo yanapaswa kuonyesha 200. Ikiwa bado yanaonyesha 100, endesha docker compose config na uthibitishe kuwa command unayotarajia ipo kwenye matokeo yaliyojumuishwa. Faili za Compose merges hubadilisha command moja kwa moja, haziongezi kwenye faili iliyopo, kwa hivyo faili ya pili inayoweka command: itashinda kimyakimya.

${POSTGRES_PASSWORD} iliyo hapo juu hupanuliwa na Compose kwenye host kutoka kwenye faili yako ya .env, kabla ya container kuwepo. Faili za Env na siri katika Compose inaelezea mahali ambapo thamani hiyo inaweza kuhifadhiwa kwa usalama.

Kuendesha migration ya mara moja kwa kutumia docker compose run

docker compose run hutengeneza container mpya kutoka kwenye ufafanuzi uleule wa huduma na kubadilisha command na chochote unachokiandika baada ya jina la huduma. Entrypoint ya image bado huendeshwa, kwa hivyo container huandaliwa sawasawa na ile inayofanya kazi kwa muda mrefu.

docker compose run --rm app python manage.py migrate
  • --rm hufuta container wakati command inapomaliza kufanya kazi. Bila flag hii, kila uendeshaji huacha container iliyosimamishwa nyuma, inayoweza kuonekana kwenye docker compose ps -a.
  • Port hazichapishwi. Container ya run hupuuza ports: ya huduma isipokuwa uongeze --service-ports, kwa hivyo haiwezi kugongana na huduma ambayo tayari inafanya kazi.
  • Dependencies huanza kwanza. Kila kitu kilicho kwenye depends_on huwaka kabla ya command yako, na --no-deps huruka hatua hiyo.
  • Container hupata jina lililozalishwa kama myproject-app-run-9f2c1a, kwa hivyo haligongani kamwe na container ya huduma.

Ili kubadilisha entrypoint pia, kuna flag maalum kwa ajili hiyo:

docker compose run --rm --entrypoint /bin/sh app -c 'python manage.py migrate'

Orodha ya argument inayotokana na hapo ni /bin/sh -c 'python manage.py migrate', kwa sababu maneno yanayofuata jina la huduma bado ni command. docker compose exec ni zana nyingine na inafanya kazi kwa njia tofauti: huendesha mchakato ndani ya container ambayo tayari inafanya kazi, na hupuuza entrypoint: na command: kabisa. Tumia run kwa kazi inayohitaji container mpya, na exec ili kuangalia ndani ya container inayofanya kazi. Compose command cheat sheet huweka subcommands nyingine zote kando kando.

Kwa nini container yangu inajifunga mara moja?

Anza na exit code, kwa sababu inafupisha muda wa kutafuta chanzo cha tatizo.

docker compose ps -a
docker compose logs app

Exit code 0 na hakuna output. Amri imetekelezwa na kumalizika. Sababu ya kawaida ni override ya entrypoint: iliyoondoa CMD ya image, hivyo entrypoint ilianza bila hoja (arguments) na haikuwa na kitu cha kuendeleza.

Error inayoishia na permission denied. Script haina executable bit ndani ya image, mara nyingi kwa sababu bit hiyo haikuwahi kuwekwa kwenye faili katika repository. Iweke wakati wa build kwa kutumia COPY --chmod=0755 entrypoint.sh /entrypoint.sh.

Error inayoishia na no such file or directory kwa faili unaloliona wazi ndani ya image. Script ina line endings za Windows. Line yake ya kwanza inasomeka kama #!/bin/sh pamoja na byte ya carriage return, kwa hivyo kernel inatafuta interpreter yenye byte hiyo kwenye jina lake na haipati kitu. Tekeleza dos2unix entrypoint.sh, kisha ongeza * text eol=lf kwenye .gitattributes ili tatizo lisijirudie.

executable file not found in $PATH. Binary iliyotajwa kwenye command: haipo ndani ya image, au umeandika shell built-in kama cd mahali ambapo programu halisi pekee ndiyo inapaswa kuwepo.

Kupata shell kwenye image ambayo entrypoint yake inafeli

Wakati entrypoint inakufa kabla hujaweza kukagua chochote, iweke nyingine:

docker compose run --rm --entrypoint /bin/sh app

Ikiwa hiyo inarudisha executable file not found in $PATH, image hiyo haina shell kabisa. Image za Distroless na zile zinazotegemea scratch mara nyingi haziji na shell. Bado unaweza kusoma mfumo wa faili kutoka nje bila kuanzisha entrypoint:

docker create --name probe myapp:1.4
docker export probe | tar -tv | head -40
docker rm probe

Wakati unahitaji container ibaki ikiwa imewaka ili uweze kuingia ndani yake mara kwa mara, iweke kwenye mchakato (process) ambao haumaliziki kamwe. Weka hili kwenye faili ya override ambayo hutaifanyia commit:

services:
  app:
    entrypoint: ["tail", "-f", "/dev/null"]
    command: []

command: [] si lazima sana, kwa sababu kuweka entrypoint: tayari kumeshafutia image hiyo CMD yake, lakini kuiandika kunarekodi nia kwa yeyote atakayesoma faili hiyo baadaye. Ianzishe na uingie ndani:

docker compose -f compose.yaml -f compose.debug.yaml up -d app
docker compose exec app /bin/sh

Sasa endesha entrypoint halisi kwa mkono na uangalie inapoishia. Hiyo inakupa ujumbe wa hitilafu kwenye terminal yako badala ya kwenye container iliyokufa nusu sekunde iliyopita. Ikiwa bado unajenga stack yako ya kwanza, stack ya kwanza ya Compose kwenye VPS inaelezea mpangilio wa faili ambao kila kitu hapo juu kinategemea.

FAQ

Kwa nini container yangu inazima mara tu baada ya docker compose up?

Angalia docker compose ps -a ili kuona exit code. Exit 0 bila ujumbe wowote kwa kawaida inamaanisha umeweka entrypoint: kwenye huduma hiyo, jambo ambalo pia limefuta CMD ya image, hivyo entrypoint imeendeshwa bila hoja (arguments) na kumaliza kazi. Ongeza hoja hizo tena kwa kutumia command:. Hitilafu inayoishia na permission denied inamaanisha script ya entrypoint haina ruhusa ya kutekelezwa (executable bit). Hitilafu inayoishia na no such file or directory kwa faili lililopo inamaanisha script hiyo ina line endings za Windows, hivyo mstari wa shebang unatafuta interpreter ambayo haipo.

Je, kuweka entrypoint katika Compose kunaondoa CMD ya image?

Ndiyo. Ikiwa entrypoint si null, Compose hupuuza amri yoyote ya msingi iliyotangazwa na image. Hiyo ni tabia iliyoandikwa kwenye nyaraka na inalingana na docker run --entrypoint. Sababu ni kwamba CMD ya image huandikwa kama hoja kwa ajili ya ENTRYPOINT ya image hiyo, kwa hivyo ukishabadilisha entrypoint, hoja za zamani hazina tena sehemu ya kutumika. Weka command: katika huduma hiyo hiyo ikiwa entrypoint mpya bado inahitaji hoja.

Je, string katika amri ya Compose huendeshwa kupitia shell?

Hapana. Tofauti na CMD ya Dockerfile, string katika command: ya Compose hugawanywa katika hoja na kutekelezwa moja kwa moja, bila kanga ya /bin/sh -c. Kwa hivyo $VARIABLE haipanuliwi kamwe na shell ndani ya container. Iite shell mwenyewe unapohitaji, kama ilivyo katika command: /bin/sh -c 'echo "hello $$HOSTNAME"'. Alama mbili za $$ hufanya escape ya alama ya dola ili Compose ipitishe alama hiyo kwenye container badala ya kuipanua kwenye host.

Kwa nini docker compose down inachukua sekunde kumi kwa container moja?

Compose hutuma SIGTERM kwa PID 1, husubiri kwa muda wa stop_grace_period (sekunde 10 kwa chaguo-msingi), kisha hutuma SIGKILL. Kernel haitumii hatua za kawaida za signal kwa PID 1, kwa hivyo programu isiyo na handler ya SIGTERM hupuuza signal hiyo na kusubiri muda wote ukamilike. Tafuta PID 1 halisi ni nini kwa kutumia docker compose exec -T app cat /proc/1/cmdline | tr '\0' ' '. Ikiwa ni shell, badilisha image iwe katika exec form au andika exec ndani ya string ya shell. Ikiwa mchakato huo unazalisha watoto (children) ambao hauwafungi, weka init: true kwenye huduma hiyo.

#docker-compose#entrypoint#command#containers#debugging