Docker Part 6 - Create Image 2

สร้าง Image กันต่อ

จากตอนที่แล้วเรารู้วิธีการสร้าง Image กันแล้วซึ่งเป็นการใช้ Dockerfile แล้วก็ใช้คำสั่งต่างๆใน Dockerfile ไม่ว่าจะเป็น FROM RUN ADD แต่เรายังขาดคำสั่งสำคัญอยู่ซึ่งมันสำคัญมาก (แล้วทำไมไม่พูดตอนที่แล้ว ฮ่าๆๆๆๆ) ซึ่งมันคือคำสั่ง CMD และ ENTRYPOINT ซึ่งเป็นคำสั่งซึ่งกำหนดว่า container ที่สร้างจาก Image พอสร้างเสร็จแล้วจะให้เขาทำงานด้วยคำสั่งอะไร

CMD

มาเริ่มที่คำสั่ง CMD กันก่อน อันนี้เราลองไปดู Image คนอื่นกันก่อน

Image httpd เขา Show dockerfile ของเขาให้ดูประมาณนี้ https://hub.docker.com/layers/httpd/library/httpd/latest/images/sha256-1fa8b506b23df25b3e2570cd27eb7a88c6d1622e749b7931e9a7f8390d17777b

จากภาพจะเห็นว่า CMD ที่กรอบแดงไว้เรียกใช้คำสั่ง httpd-foreground ซึ่งเมื่อเราลองสั่ง

1
docker run --name test_httpd httpd

จะได้ดังภาพ

ซึ่งตรงกับที่บอกไว้ในคำสั่ง CMD ตรงนี้อาจจะบอกว่ามั่วรึเปล่า งั้นเรามาเปลี่ยน CMD กันดูว่าถ้าเราทำการแก้ไข CMD กันดูแล้วดูว่าจะมีการเปลี่ยนเปลงหรือไม่ โดยทำการสร้างไฟล์ Dockerfile ขึ้นมาโดยใส่คำสั่งในการสร้าง image ไว้ดังนี้

1
2
FROM httpd
CMD ["echo", "hello world Matilda"]

จากนั้นสั่งทำการสร้าง Image

1
docker build -t test_change_cmd .

จากนั้นทำการสั่งสร้าง container

1
docker run --name test_container  test_change_cmd

ซึ่งผลลัพธ์จะเป็นดังภาพซึ่งจะเห็นว่า container ของเราทำการแสดงผล hello world Matilda ออกมา ซึ่งตรงกับที่เราสั่งไว้ และจะเห็นด้วยว่า container ของเราจะไปอยู่ในสถานะ stop ซึ่งมันก็ปกติเพราะมันทำงานคำสั่ง echo hello world Matilda เสร็จแล้ว ทำให้ container ทำการหยุดทำงาน ต่างจาก image httpd สั่งให้ใช้คำสั่ง httpd-foreground ซึ่งเป็นคำสั่งที่ทำงานแบบ infinity loop คือทำไปเรื่อยๆไม่มีจุดจบทำให้ container นั้นไม่มีวันหยุดทำงาน

ENTRYPOINT

ENTRY POINT ก็คล้ายๆกับ CMD เลยครับ คือจะให้ Container ที่สร้างจาก Image นี้ทำการ run คำสั่งอะไร ถึงตรงนี้ผมบอกเลยว่าคุณจะงงแน่นอน แต่ขอให้ลองทำครับขั้นแรกเรามาสร้าง Dockerfile โดยมีวิธีการสร้าง Image ดังนี้

1
2
FROM httpd
ENTRYPOINT ["echo", "hello world Matilda"]

จากนั้นลอง build image ด้วยคำสั่งนี้ดูครับ

1
docker build -t test_entrypoint .

จากนั้นลองทำการ container ด้วยคำสั่งนี้ดูครับ

1
docker run --name container_entrypoint test_entrypoint

ซึ่งจะได้ผลลัพธ์ดังภาพ ซึ่งจะเหมือนกับ CMD เลย ซึ่งทั้งคำสั่ง CMD และ ENTRYPOINT เป็นการบอกว่าจะ Container ที่สร้างขึ้นมาจาก Image จะทำงานด้วยคำสั่งอะไร แต่มันมีข้อแตกต่างกันนิดหน่อยซึ่งจะอธิบาย ณ บัดนี้

CMD vs ENTRYPOINT

ทั้งสองทำงานคล้ายๆกันแต่แตกต่างกันนิดหน่อย เราลองมาเล่นคำสั่ง docker run ไปทีละคำสั่งครับ

1
2
3
4
docker run --rm test_change_cmd 
docker run --rm test_entrypoint

# --rm เป็น option ของ docker run ที่จะทำการลบ container ลงทันทีเมื่อ

ได้ผลลัพธ์เหมือนกัน คราวนี้มาลอง

1
2
docker run --rm test_change_cmd Harupiii
docker run --rm test_entrypoint Harupiii

คราวนี้จะไม่เหมือนกันละ จากภาพจะเห็นว่าสั่งด้วย image ที่ใช้ CMD จะ error แต่ที่ใช้ ENTRYPOINT จะไม่ Error คราวนี้เรามาลองดูแบบละเอียดกันครับ

1
2
3
4
5
6
7
8
9
docker run --rm test_change_cmd Harupiii
docker run --rm test_entrypoint Harupiii

# Harupiii เป็นค่าที่เราใส่ไปหลังชื่อ Image โดยคำสั่ง docker run จะเอาค่าไปจัดการยังไงต่อนั้นมัน
# จะตามเงื่อนไขว่าเป็น CMD หรือ ENTRY POINT

# ถ้า Image นั้นใช้ CMD สิ่งที่อยู่หลัง Image ทั้งหมดจะไปอยู่แทน CMD ของ Image ว่าง่ายๆ container ตัวนี้ถูกบังคับให้ run ด้วยคำสั่ง Harupiii นั่นเอง ซึ่งมันทำให้เกิด Error ขั้นนั่นเอง เพราะไม่มีคำสั่งที่ชื่อ Harupiii นั่นเอง

# ถ้า Image นั่นใช้ ENTRYPOINT สิ่งที่อยู่หลัง Image จะถูกเอาไปต่อหลังคำสั่งที่อยู่ใน ENTRYPOINT จากตัวอย่างอันนี้เราจะได้ว่า container จะ run ด้วยคำสั่ง echo hello world Matilda Harupiii ด้วยเหตุนี้มันเลยไม่ Error

เพื่อให้เข้าใจมากยิ่งขึ้นเรามาลองเล่นแบบนี้ดู

1
2
docker run --rm test_change_cmd ls
docker run --rm test_entrypoint ls

คราวนี้ไม่ Error ทั้งคู่ โดยฝั่ง CMD จะใช้คำสั่ง ls ซึ่งทำการ list file and directory ในปัจจุบันออกมา ส่วนฝั่ง ENTRYPOINT ยังคงเป็นการ echo คำออกมาแต่เป็นการเปลี่ยนเป็น hello world Matilda ls

แล้วจะใช้อะไร

ถ้าเอาง่ายๆก็คือ ถ้าใช้ CMD คือเราอยากให้ Container ที่ Run จาก Image นั้น run คำสั่งที่เหมือนกันไม่ต้องมีการ Customize ตัวคำสั่งที่อยาก run เช่นอย่าง image httpd นี้เขาใช้ CMD คือเขาอยากให้ Image นี้ run ด้วยคำสั่ง httpd-foreground เท่านั้น ส่วนการ config อื่นๆให้ไปทำกันที่ Environment หรือการ mount volume file config เอา แต่ถ้าใช้ ENTRYPOINT อันนี้คือเขาต้องการให้สามารถ customize คำสั่งตอน run container ได้ประมาณว่า run โดยใช้ parameter อะไรบ้างเป็นต้น โดยเขาจะใช้วิธีการสร้างไฟล์ .sh ขึ้นมาสักตัว ประมาณนี้ โดยตัวอย่างเราจะทำเป็นไฟล์ชื่อ entrypoint.sh จากนั้นในไฟล์ entrypoint ก็รับ parameter เข้ามาเพื่อให้ทำอะไรบางอย่าง เช่นตัวอย่างผมจะรับ parameter เข้ามาเพื่อทำอะไรบางอย่างที่แตกต่างกันเช่น

ไฟล์ entrypoint.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if [ "$1" = "" ] 
then
echo "Case no parameter"
elif [ "$1" = "infinity" ]
then
echo "Case run infinity loop"
while :
do
echo "IN LOOP"
sleep 1
done
else
echo "Case other"
fi

อันนี้คือเราจะรับ parameter ให้กับ entrypoint.sh โดยถ้า parameter ตัวแรกที่ส่งเข้ามาเป็นคำว่า infinity จะทำการ Run แบบ infinity loop

ส่วน Dockerfile จะเป็น

1
2
3
FROM httpd
ADD entrypoint.sh ./
ENTRYPOINT ["bash", "/usr/local/apache2/entrypoint.sh"]

จากนั้นสร้าง image ด้วยคำสั่ง

1
docker build -t test_entrypoint .

จากนั้นลองใช้ docker run แบบต่างๆดังนี้

1
2
3
docker run --rm  test_entrypoint
docker run --rm test_entrypoint nico
docker run --rm test_entrypoint infinity

สรุป

สำหรับตอนนี้เรามาทำความเข้าใจคำสั่งสองคำสั่งคือ CMD และ ENTRYPOINT ซึ่งเราได้ลองใช้งานทั้งสองคำสั่งและความแตกต่างของแต่ละคำสั่ง ซึ่งน่าจะสามารถนำไปประยุกต์ใช้งานในการสร้าง Image ได้ในระดับที่เอาไปใช้ได้ในงานจริงแล้ว (ผมรู้แค่นี้ก็เอาไปขึ้น Production ได้แล้ว) สำหรับตอนนี้ขอจบลงเพียงเท่านี้ครับ

โปรโมท Page

ผมทำ Page บน Facebook แล้วนะครับ ใครสนใจรับการแจ้งเตือนเวลาผมอัพเดท Blog ก็ไปกดติดตามกันได้ครับ กดตามลิ้งไปได้เลย Facebook : Normal Programmer

ไม่เกี่ยวกับ Docker แต่เกี่ยวกับไอดอล

Matilda

Matilda

Harupii

Harupii

เพลงประกอบการเขียน Blog

เนื้อเพลงนี่แบบใช่เลย ไปร้องเพลงให้สาวฟังก็ไม่รู้จะป็นยังไง ชอบตรงการเล่นกับคำว่าหมื่นล้านเพลง เวอร์ชันต้นฉบับของพี่บิลลี่ โอแกน เวอร์ชันนี้ละมุนแบนด์เอามา cover ร้องแข่งในรายตำนานหมู่ คือร้องสด เล่นกีตาร์สด แบบ โอ้ยฟินโคตรๆ