การใช้งาน cmd และ entrypoint ใน Dockerfile

DevOps Dec 24, 2019

ใน Dockerfile จะมีคำสั่งสองคำสั่งที่ทำงานคล้ายกันมากคือ CMD และ ENTRYPOINT ซึ่งโดยวิธีใช้ทั้งสองอันจะเป็นการเรียกชุดคำสั่ง (command หรือ executables) สุดท้ายก่อนที่ docker จะสร้าง container ขึ้นมา

ทั้ง cmd และ entrypoint มีวิธีการเขียนดังนี้

CMD ["executable", "arg1", "arg2"]
ENTRYPOINT ["executable", "arg1", "arg2"]

เวลาตอนสร้าง Container ขึ้นมามันก็จะถูกเรียกใช้แบบนี้

CMD executable arg1 arg2
ENTRYPOINT executable arg1 arg2

CMD

CMD เอาไว้กำหนด default executable หรือ default arguments ให้กับ Dockerfile ของเรา เช่น

Default executable

CMD ["node", "index.js"]

Default arguments

โดยเราจะใช้งานร่วมกับ ENTRYPOINT

CMD ["index.js"]
ENTRYPOINT ["node"]

Entrypoint

ENTRYPOINT เอาไว้กำหนด default executable ซึ่งสามารถใช้ร่วมกับ CMD ได้ โดยให้ CMD เป็นตัวกำหนดค่าพารามิเตอร์ให้ ENTRYPOINT ดังตัวอย่างก่อนหน้านี้ หรือเรียกใช้งานแบบนี้ก็ได้

ENTRYPOINT ["node", "index.js"]

ตัวอย่างการใช้งาน

เรามาดูตัวอย่างการใช้งาน CMD และ ENTRYPOINT กันว่ามันทำงานยังไง โดยผมจะใช้คำสั่ง cowsay และ screenfetch เป็นตัวอย่างการแสดงผล

ตัวอย่างที่ 1

ใช้ CMD กำหนด default executable ให้ทำการสร้างไฟล์ชื่อ Dockerfile-cmd แล้วใส่คำสั่งดังนี้

FROM debian:jessie-slim

RUN apt-get update && \
  apt-get install -y --no-install-recommends \
  cowsay \
  screenfetch && \
  rm -rf /var/lib/apt/lists/*

ENV PATH "$PATH:/usr/games"
CMD ["cowsay", "Yo, CMD !!"]

สร้าง Image: docker build -t demo:cmd -f Dockerfile-cmd .

สร้าง Container: docker run --rm demo:cmd

เราจะได้ผลลัพธ์ดังนี้

$ docker run --rm demo:cmd
 ____________
< Yo, CMD !! >
 ------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

อย่างไรก็ตามเราสามารถใส่ command อันใหม่แทนได้ โดยพิมพ์ต่อท้าย docker run --rm demo:cmd screenfetch -E

เราจะได้ผลลัพธ์ดังนี้

$ docker run --rm demo:cmd screenfetch -E
         _,met$$$$$gg.           @0cc9e5da8bca
      ,g$$$$$$$$$$$$$$$P.        OS: Debian 
    ,g$$P""       """Y$$.".      Kernel: x86_64 Linux 4.15.0-72-generic
   ,$$P'              `$$$.      Uptime: 4h 0m
  ',$$P       ,ggs.     `$$b:    Packages: 106
  `d$$'     ,$P"'   .    $$$     Shell: 
   $$P      d$'     ,    $$P     CPU: Intel Core i5-8250U CPU @ 3.4GHz
   $$:      $$.   -    ,d$$'     RAM: 4334MB / 7873MB
   $$\;      Y$b._   _,d$P'     
   Y$$.    `.`"Y$$$$P"'         
   `$$b      "-.__              
    `Y$$                        
     `Y$$.                      
       `$$b.                    
         `Y$$b.                 
            `"Y$b._             
                `""""    

ตัวอย่างที่ 2

เรามาลองใช้งาน ENTRYPOINT ในการกำหนด default executable กัน ให้สร้างไฟล์ชื่อ Dockerfile-entry แล้วพิมพ์ดังนี้

FROM debian:jessie-slim

RUN apt-get update && \
  apt-get install -y --no-install-recommends \
  cowsay \
  screenfetch && \
  rm -rf /var/lib/apt/lists/*

ENV PATH "$PATH:/usr/games"
ENTRYPOINT ["cowsay", "Yo, Entrypoint!!"]

สร้าง Image: docker build -t demo:entry -f Dockerfile-entry .

สร้าง Container: docker run --rm demo:entry

เราจะได้ผลลัพธ์ดังนี้

$ docker run --rm demo:entry
 __________________
< Yo, Entrypoint!! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

แต่คราวนี้ถ้าเราอยากจะใส่ command ชุดใหม่ไปแทนแบบ CMD มันจะไม่สามารถทำได้ แต่จะเป็นการส่งค่า arguments ไปแทน เช่น docker run demo:entry screenfetch -E

เราจะได้ผลลัพธ์ดังนี้

$ docker run --rm demo:entry screenfetch -E
 _________________________________
< Yo, Entrypoint!! screenfetch -E >
 ---------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

ตัวอย่างที่ 3

เรามาลองใช้งาน ENTRYPOINT และ CMD ด้วยกัน ซึ่งการใช้งานแบบนี้หาก ENTRYPOINT ถูกกำหนดแล้ว CMD จะถูกมองให้เป็น arguments ไปยัง ENTRYPOINT ทันที ให้สร้างไฟล์ชื่อ Dockerfile-cmd-entry แล้วพิมพ์ดังนี้

FROM debian:jessie-slim

RUN apt-get update && \
  apt-get install -y --no-install-recommends \
  cowsay \
  screenfetch && \
  rm -rf /var/lib/apt/lists/*

ENV PATH "$PATH:/usr/games"

CMD ["Yo, CMD!!"]
ENTRYPOINT ["cowsay", "Yo, Entrypoint!!"]

สร้าง Image: docker build -t demo:cmd-entry -f Dockerfile-cmd-entry .

สร้าง Container: docker run --rm demo:cmd-entry

เราจะได้ผลลัพธ์ดังนี้

$ docker run --rm demo:cmd-entry
 ____________________________
< Yo, Entrypoint!! Yo, CMD!! >
 ----------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

ซึ่งเราสามารถแทนค่า arguments ที่กำหนดไว้ใน CMD ได้ง่ายๆ ดังนี้ docker run --rm demo:cmd-entry Overriding arg passed in cmd

เราจะได้ผลลัพธ์ดังนี้

$ docker run --rm demo:cmd-entry Overriding arg passed in cmd
 ________________________________________
/ Yo, Entrypoint!! Overriding arg passed \
\ in cmd                                 /
 ----------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

ก็ลองไปปรับใช้กันดูนะครับสำหรับ CMD และ ENTRYPOINT

Happy docker :)

Thanks: dev.to/lasatadevi/docker-cmd-vs-entrypoint-34e0

Arnon Kijlerdphon

IT manager & DevOps @Twin Synergy Co.,Ltd

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.