Jaynarol Blog

Docker : รู้จักและใช้งาน Dockerfile

         สวัสดีครับ หลังจากได้เห็นภาพรวมการใช้งาน Docker ไปบ้างเล็กน้อยจากบทความก่อนๆ วันนี้ผมจะลงรายละเอียดเรื่องที่มาที่ไปของ Docker image และการสร้าง Docker image ของเราเองด้วย Dockerfile ครับ สำหรับท่านที่ยังไม่เคยเล่น Docker จริงๆจังๆ ก่อนเข้าเนื้อหาบทความหลักผมอยากย้ำตรงนี้ให้ทราบก่อนนิดนึงครับว่า ความสามารถของ Docker นั้นเจ๋งและทรงพลังมาก บทความนี้เป็นแค่ติ่งเล็กๆของพื้นฐานเองครับ ที่ต้องบอกไว้ก่อนเพราะกลัวจะเบื่อและคิดว่า Docker ไม่มีอะไรน่าสนใจไปซะก่อน ยังไงรอติดตามบทความผมไปเรื่อยๆผมจะพารู้ไปทีละขั้นๆนะครับ

 

ทักทาย Dockerfile

      หากใครเคยเข้าไปที่เว็บ Docker Hub (ผมคิดว่าเคยเข้าทุกคนนะ) ซึ่งเป็น Docker image repository สาธารณะที่ใหญ่ที่สุด เราจะพบว่ามี Docker image ที่พร้อมให้โหลดไปใช้อยู่มากมาย คำถามคือ Docker image พวกนี้มาจากไหน? แน่นอนว่าเป็นสิ่งที่ผมกำลังพูดถึงในหัวข้อนี้ ซึ่งก็คือมาจาก Dockerfile นั่นเอง

1

ถ้าสังเกตให้ลึกไปอีกเราจะพบว่าเมื่อเราเข้าไปในแต่ละ Repo มักจะมีการอ้างถึงไฟล์ Dockerfile ของเวอร์ชั่นนั้นๆด้วยเสมอ (ซึ่งบาง Repo อาจจะอยู่ด้านข้างหรือตรงอื่นแล้วแต่ที่มาของ Docker image) ในภาพตัวอย่างด้านบนผมเลือกเป็น Repo WordPress พอกดไปที่ apache/Dockerfile ก็จะไปโผล่ที่ github และแสดงข้อมูล text file ขึ้นมา สังเกตง่ายๆ หากเห็นว่าบรรทัดแรกขึ้นต้นด้วย FROM something ไอ้เจ้า text file ตัวนี้แหละครับคือ Dockerfile

 

รู้จัก Dockerfile

         สรุปสั้นๆ Dockerfile ก็คือ text file ธรรมดาๆที่บรรจุชุดคำสั่งต่างๆที่ใช้ในการสร้าง Docker image เมื่อเรา Build Dockerfile ด้วยคำสั่ง docker build ข้อมูลต่างๆใน Dockerfile จะถูกแปลงไปเป็น Command ของ Linux อีกทีนึงและทำงานจากบรรทัดแรกของไฟล์ยันบรรทัดสุดท้าย อารมณ์มันคล้ายๆเราสั่งติดตั้ง Service สักตัวบน Linux ผ่าน Command Line ทีละคำสั่งจนเสร็จแหละครับ แต่สิ่งที่แตกต่างคือตอนติดตั้งเสร็จ Docker มันสามารถห่อข้อมูลทั้งหมดที่ทำงานตามคำสั่งไปแล้ว มาเก็บไว้ในไฟล์ได้ ซึ่งก็คือ Docker image นี่เองครับ

ภาพจะคล้ายๆการพัฒนาโปรแกรม เปรียบ Dockerfile คือ Source code พอ Compile เสร็จก็จะได้ตัวติดตั้ง Software มา ซึ่งเปรียบก็คือ Docker image พอนำไปติดตั้งก็จะได้เป็นโปรแกรมตัวนึง ซึ่งก็คือ Docker Container ครับ

  • Source Code → Setup.exe → Application
    Dockerfile → Docker image → Docker Container

ใครที่จะเขียน Dockerfile เองนั้นหากมีพื้นฐานในการใช้งาน Command Line บน Linux มาบ้างจะช่วยได้เยอะครับ เพราะข้อมูลที่เราต้องเขียนลงไปในไฟล์มันคือขั้นตอนการติดตั้ง Service สักตัวตามปกติดีๆนี่เอง

 

ความเจ๋งของ Dockerfile

         Dockerfile คือชุดคำสั่งทั้งหมดที่เราต้องใช้ติดตั้ง Service สักตัว จะเข้าใจแบบนี้ก็ไม่ผิดนัก แต่ลองคิดตามเล่นๆหาก Service หลักของเรามันคือ WordPress ที่ต้องติดตั้งและตั้งค่า Service ย่อยอื่นๆก่อนมากมาย การเขียน Dockerfile คงนรกแน่ๆ แต่ไม่ต้องห่วงครับ Docker ได้ทำการบ้านในการแก้ไขจุดนี้มาอย่างดีเพราะ Dockerfile ทุกตัวสามารถสืบทอด Docker image ตัวอื่นๆได้ ทำให้เราไม่ต้องไปเริ่มใหม่ตั้งแต่ต้นครับ ถ้ายังงงๆให้ดูตามตัวอย่างนี้ครับ

สังเกตตรง FROM ... ที่บรรทัดแรกของแต่ละอันจะเห็นได้ว่าใน Dockerfile ของ Official WordPress ก็มีการสืบทอดมาจาก Official php:5.6/apache และก็สืบทอดต่อๆกันจนไปบนสุดคือ scratch (เป็น image ว่างเปล่า) ดังนั้น ในเคสของเราจึงมีทางเลือกมากมายตั้งแต่ง่ายสุดคือ สืบทอดจาก image ของ Official WordPress แล้วมาโมนิดๆหน่อยๆตามที่เราต้องการ หรือ สืบทอดจาก image ของ Official php แล้วติดตั้ง wordpress เอง หรือหากเป็นงานที่ต้องใช้ความปลอดภัยสูงมากๆ ทุกคำสั่งต้องได้รับการรีวิว ก็เริ่มจาก scratch เลยก็ได้ เป็นต้นครับ

 

ประโยชน์ของ Dockerfile

  1. เราสามารถสร้าง Docker image เองได้อย่างง่ายดายด้วยการสืบทอด Docker image อื่นๆ
  2. เราสามารถสร้าง Service ที่มีหลากหลายเวอร์ชั่นได้ง่ายขึ้นมากๆ
  3. เราสามารถเก็บ Dockerfile แทน Docker image ได้เลย เล็กและดูแลง่ายกว่ามาก ไว้จะใช้งานค่อย build เอา
  4. เราสามารถเลือกที่จะส่ง Dockerfile ไปให้เพื่อนแทน Docker image ก็ได้ แล้วแต่จุดประสงค์ของงาน
  5. เพื่อความสบายใจ เราสามารถใช้ Dockerfile เพื่อรีวิว Docker image อื่นๆว่าใช้คำสั่งอะไรไปแล้วบ้างได้ด้วย (แต่ต้องระวังนิดนะครับเพราะอนาคตอาจโดนเปลี่ยนเมื่อไหร่ก็ได้)

 

ลองเล่นกันดีกว่า

         ในหัวข้อนี้ผมจะพาเล่นเล็กๆน้อยๆเพื่อให้เห็นภาพวงจรการทำงานของ Dockerfile นะครับ จะไม่เน้นเรื่องการใช้ Dockerfile Command เพราะมันยาวมากจนแยกไปอีกบทได้เลย และที่สำคัญคือต้องมีความรู้พื้นฐานเรื่อง Linux Command ด้วย ซึ่งจะผิดวัตถุประสงค์ของบทความนี้ไปใหญ่ ยังไงผมคิดว่าทุกคนสามารถศึกษาเองได้ไม่ยากครับ ต้นทางเขาก็เขียนรายละเอียดพร้อมยกตัวอย่างไว้ดีแล้วด้วยครับ

 

ตั้งเป้าหมาย

เป้าหมายคิดสดๆเลยเมื่อกี้ครับ ผมอยากจะได้เว็บง่ายๆที่แสดงข้อมูลของผมเอง เก็บไว้ในรูปแบบ docker image อัพโหลดขึ้น docker hub ให้คนอื่นสามารถ pull ไปลองเปิดเล่นได้ (เกรียนดีครับ 5555+)

 

วิเคราะห์

  1. งานผมคือ เว็บ ที่เป็น html ง่ายๆดังนั้น service nginx ก็น่าจะเพียงพอแล้ว
  2. ผมลองหาข้อมูลใน docker hub เจอ official nginx ตัวนี้แหละคือ base ที่ผมต้องการสืบทอด
  3. ผมหาข้อมูลใน repo nginx ต่อจนทราบว่า Container จะอ่านไฟล์เว็บที่ /usr/share/nginx/html

 

เตรียม Account Docker Hub

ข้อนี้ใครมีแล้วข้ามไปเลยครับแต่ใครยังไม่มีให้ลงทะเบียนก่อนนะครับ

 

เตรียม Dockerfile

เราไม่ต้องกังวลเรื่อง service nginx เพราะเราจะสืบทอดมันมาทั้งยวง ดังนั้นสิ่งที่เราต้องทำจริงๆก็คือแก้ไขไฟล์ index.html ที่ /usr/share/nginx/html/ ให้เป็นข้อมูลที่เราต้องการเท่านั้นเองครับ และด้วยความมักง่ายที่ไม่ควรเอาเยี่ยงอย่างผมจะระบุคำสั่งที่ใช้แก้ไขไฟล์ html ลงไปใน Dockerfile เลยครับ (วิธีที่ดีกว่านี้คือเขียนไฟล์ html แยกออกมาและใช้คำสั่ง copy ไปทับเอาครับ)

ให้เปิด Docker Terminal ขึ้นมาแล้วใส่ command ดังนี้ครับ

 

จากนั้นจะได้ Dockerfile หน้าตาเหมือนรูปด้านล่าง อยู่ที่โฟลเดอร์ ~/my-dockerfile ครับ ให้แก้ไขข้อความที่เป็น html ได้ตามใจชอบครับ (ถ้าไม่แก้มันจะเป็นข้อมูลของผมนะ :D)

 

สร้าง image

หลังจากมี Dockerfile ของเราเองแล้วที่เหลือง่ายนิดเดียวครับ ใช้คำสั่งดังนี้

(เปลี่ยน docker-hub-id เป็นของตัวเอง และ ตั้งชื่อ myprofile ได้เองตามใจชอบครับ)

docker build -t docker-hub-id/myprofile .

จากนั้นลองพิมพ์คำสั่ง docker images จะพบว่ามี images ของเราปรากฎขึ้นมาบนลิสด้วย เป็นอันเสร็จครับ ได้ docker image ของเราเองแล้ว

 

ทดลองใช้งาน

สั่ง run image ของเราตามปกติได้เลยครับ

(อย่าลืมเปลี่ยน docker-hub-id/myprofile เป็นของตัวเองนะครับ)

docker run -d -p 80:80 --name myprofile docker-hub-id/myprofile 

เมื่อรันเสร็จให้ลองเปิดเว็บโดยใช้ไอพีของเครื่อง docker ครับ (ใครไม่ทราบ ip ของ docker ให้ใช้คำสั่ง docker-machine ip ครับ)

หลังเปิดเว็บแล้วเราควรจะพบเว็บของเราแสดงผลขึ้นมาครับ หากใครไม่ขึ้นแสดงว่าพลาดขั้นตอนอะไรไปแน่ๆ ให้ลองไล่ดูใหม่นะครับ หรือคอมเม้นไว้ด้านล่างได้เลยเดี๋ยวผมช่วยดูให้ครับ

หลังจากชื่นชมจนพอใจแล้ว หากต้องการหยุดการทำงานของ Container ใช้คำสั่ง docker stop myprofile และหากต้องการลบก็ docker rm myprofile นะครับ (ลบแค่ Container ไม่ได้ลบ image ครับ)

 

เผยแพร่ขึ้น docker hub

ก่อนที่เราจะอวดต่อสายตาชาวโลก อันดับแรกต้อง login docker hub ใน terminal ก่อนครับโดยใช้คำสั่ง docker login และกรอกข้อมูลตามปกติ

เมื่อเสร็จแล้วเราจะ push image ของเราด้วยคำสั่งนี้ครับ

docker push docker-hub-id/myprofile 

 

หลังจาก push เสร็จแล้วเราจะเห็น image ของเราขึ้นไปลอยลำบน docker hub และสามารถให้ใครก็ได้ทั่วโลก pull ลงไปเปิดเล่นได้เลยครับ (บางครั้งอาจต้องใช้เวลาสัก 5 นาทีถึงจะเห็น image เราอัพขึ้นบนเว็บนะครับ)

ถ้าใครอยากรู้ว่า image บน docker hub ของเราเวิร์กไหม ให้ลบ image ในเครื่องตัวเอง docker rmi -f docker-hub-id/myprofile และลองสั่ง run ดูนะครับ จะพบว่ามันไปดึง image ที่ docker hub มาให้เราและทำงานได้เหมือนเดิมครับ

 

ปิดท้าย

บทความนี้เน้นความเข้าใจว่า Dockerfile คืออะไร และพาลองใช้แบบคร่าวๆเพื่อให้เห็นภาพการทำงาน แน่นอนว่าเนื้อหาอาจไม่มากพอที่จะนำไปใช้งานจริงได้ทันทีแต่ก็เพียงพอเหลือเฟือสำหรับการนำไปต่อยอด สำหรับคนที่ต้องการต่อยอดผมแนะนำให้อ่าน Document ของ Docker โดยตรงเลยซึ่งมีรายละเอียดครบถ้วนมากพออยู่แล้ว หากใครที่เข้าไปอ่านแล้วงงก็ไม่ต้องแปลกใจครับ แสดงว่าพื้นฐานด้าน Linux Command ยังไม่แน่นพอ อาจต้องไปเพิ่มพูนตรงนั้นก่อนครับ

บทความหน้าผมจะพยายามหาเวลามาเขียนเรื่อง docker-compose รับรองว่าน่าสนใจและมีประโยชน์มาก

แล้วพบกันใหม่ครับ สวัสดีครับ