การสร้าง Docker Image จาก Scratch

Creating Docker Image From Scratch



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

พูดอย่างหลวม ๆ ว่า Docker กลายเป็นเหมือนตัวจัดการแพ็คเกจสากลซึ่งทำงานบนแพลตฟอร์ม Linux ที่เป็นไปได้ทั้งหมด ต้องใช้คอนเทนเนอร์และใช้เพื่อแก้ปัญหาที่แตกต่างอย่างสิ้นเชิงที่นักพัฒนาต้องเผชิญ ปัญหาคือนักพัฒนาใช้ระบบปฏิบัติการเดสก์ท็อป (เช่น Windows, macOS หรือ Linux พร้อมแพ็คเกจที่เกี่ยวข้องกับเดสก์ท็อปจำนวนมาก) เพื่อเขียนแอปพลิเคชัน แอปพลิเคชันที่พวกเขาเขียนมักจะทำงานบนระบบปฏิบัติการที่ต่างไปจากเดิมอย่างสิ้นเชิงบนเซิร์ฟเวอร์บางแห่งที่มีการกระจาย Linux บางตัวแตกต่างจากแล็ปท็อปของนักพัฒนาโดยสิ้นเชิง







ด้วย Docker แนวคิดก็คือแอปพลิเคชันของคุณถูกบรรจุเป็นอิมเมจของ Docker เป็นหน้าที่ของ Docker ที่จะถ่ายภาพนี้และเรียกใช้เป็นแอปพลิเคชันที่มีคอนเทนเนอร์สำหรับคุณ การทำให้เป็นคอนเทนเนอร์หมายความว่าแอปพลิเคชันและการอ้างอิงจะทำงานในสภาพแวดล้อมที่แยกออกมาซึ่งอาจแตกต่างจากแล็ปท็อปของนักพัฒนาซอฟต์แวร์และแม้แต่เซิร์ฟเวอร์ที่ใช้งานจริงโดยสิ้นเชิง ตราบใดที่ทั้งคู่รองรับ Docker ทั้งคู่ก็สามารถเรียกใช้แอปพลิเคชันเดียวกันในลักษณะเดียวกันได้



กายวิภาคของ Docker Image

ดังที่ได้กล่าวไว้ก่อนหน้านี้ แอพ Docker จะทำงานบนสภาพแวดล้อมที่ตกลงกันไว้ ตอนนี้คำถามคือเราจะสร้างสภาพแวดล้อมนั้นได้อย่างไร อิมเมจของแอพพลิเคชั่นส่วนใหญ่จะนำเข้าอิมเมจพื้นฐานของ Docker และสร้างแอพพลิเคชั่นที่ด้านบน



แอปพลิเคชันทำจากเลเยอร์ของซอฟต์แวร์ อิมเมจคอนเทนเนอร์เวิร์ดเพรสถูกสร้างขึ้นโดยใช้อิมเมจคอนเทนเนอร์ httpd ซึ่งสร้างทับอิมเมจ Ubuntu อิมเมจที่ใช้สร้างอิมเมจใหม่เรียกว่า PARENT IMAGE ในคำศัพท์เฉพาะของ Docker ใน Dockerfile (เราจะพูดถึงความหมายของ Dockerfile ในภายหลัง) รูปภาพหลักนี้ถูกกล่าวถึงที่ด้านบนของไฟล์ดังที่แสดงด้านล่าง:





จาก Ubuntu:18.04
## ส่วนที่เหลือของ Dockerfile

เมื่อดำเนินการ Dockerfile นี้จะแปลงแอปพลิเคชันของคุณเป็นอิมเมจ Docker (ไบนารีของประเภท) ซึ่งคุณสามารถพุชไปยังรีจิสตรีจากตำแหน่งที่สามารถดึงเพื่อสร้างคอนเทนเนอร์ใหม่ที่อื่น อย่างไรก็ตาม พวกเขาทั้งหมดจะมี Ubuntu:18.04 เป็นอิมเมจพื้นฐาน และทำงานราวกับว่าเป็นระบบ Ubuntu ที่พวกเขาใช้งานอยู่

คุณอาจสังเกตเห็นสิ่งนี้เมื่อพยายามดึงอิมเมจนักเทียบท่าใหม่



การสร้าง Docker Image จาก Scratch

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

ด้วยเหตุนี้ เราจึงต้องการสร้างสิ่งที่เรียกว่าภาพฐาน ที่ไม่ได้สร้างขึ้นเหนือสิ่งอื่นใด คีย์เวิร์ด scratch ใช้เพื่อระบุว่าเลเยอร์นี้ไม่ได้สร้างขึ้นเหนือสิ่งอื่นใด ชอบดังนั้น:

ตั้งแต่เริ่มต้น
## ส่วนที่เหลือของ Dcokerfile

ขั้นแรกเราจะสร้างแอปพลิเคชัน Hello World แบบง่าย ๆ แล้วค้นหาว่าส่วนที่เหลือของ Dockerfile จะเป็นอย่างไร ระบบโฮสต์คือ Ubuntu:18.04 LTS และเรากำลังใช้ Docker เวอร์ชัน 17.12.1-ce สำหรับการทดสอบ

การสร้างไบนารีแบบคงที่

คอนเทนเนอร์นักเทียบท่าคือชุดของกระบวนการที่ทำงานแยกจากส่วนที่เหลือของระบบปฏิบัติการ สิ่งเดียวที่ต้องติดต่อคือเคอร์เนล เคอร์เนลมีหน้าที่รับผิดชอบในการจัดกำหนดการกระบวนการเหล่านี้บน CPU จัดการหน่วยความจำ และงานจองพื้นฐานอื่นๆ อีกสองสามงาน

แต่แอปพลิเคชันระดับสูงส่วนใหญ่ขึ้นอยู่กับไลบรารีระบบจำนวนมาก (เช่น glibc, musl, klibc เป็นต้น ) และการพึ่งพารันไทม์จำนวนมาก เช่น Python หรือ Node.js หรือ Java Runtime ไบนารีของแอปพลิเคชันไม่มีไลบรารีทั้งหมดที่มีอยู่ แต่เมื่อเริ่มดำเนินการจะเรียกไลบรารีเหล่านั้นจากระบบปฏิบัติการโฮสต์

เนื่องจากเรากำลังพยายามสร้างภาพตั้งแต่เริ่มต้น เราจะไม่ได้รับสิ่งที่ดีงามเหล่านี้ ดังนั้นแอปพลิเคชันของเราจึงต้องเป็นไฟล์แบบคงที่หรือแบบสแตนด์อโลนที่สามารถเรียกทำงานได้

เริ่มต้นด้วยการสร้างโฟลเดอร์ชื่อ MyDockerImage และสร้างไฟล์ hello.cc ข้างใน

$mkdirMyDockerImage
$ซีดีMyDockerImage
$สัมผัสสวัสดี.cc

เปิด hello.cc โดยใช้โปรแกรมแก้ไขข้อความที่คุณชื่นชอบ และเพิ่มบรรทัดต่อไปนี้เข้าไปข้างใน

#รวม
ใช้เนมสเปซ std;
intหลัก(){
ค่าใช้จ่าย<< 'สวัสดี! ข้อความนี้มาจากคอนเทนเนอร์NS';
กลับ 0;

}

นี่เป็นโปรแกรม C++ แบบง่ายที่พิมพ์ Hello! ข้อความนี้ …

ด้วยเหตุผลที่กล่าวถึงก่อนหน้านี้ เราจะรวบรวมสิ่งนี้โดยใช้การตั้งค่าสถานะคงที่ คอมไพเลอร์ที่ใช้คือ g++ (อูบุนตู 7.3.0-16ubuntu3) 7.3.0

ในการคอมไพล์โปรแกรม ให้รันคำสั่งต่อไปนี้ในไดเร็กทอรีเดียวกัน:

$ g++ -o สวัสดี-คงที่สวัสดี.กระแสตรง

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

$./สวัสดี

ตอนนี้เราพร้อมที่จะบรรจุโปรแกรมง่ายๆ นี้แล้ว

Dockerfile

Dockerfile ประกอบด้วยชุดของกฎที่นำไฟล์แอปพลิเคชันของคุณ (เช่น ไบนารี ไฟล์ต้นฉบับ ฯลฯ) ไปพร้อมกับพารามิเตอร์การกำหนดค่าต่างๆ เช่น เลย์เอาต์ของระบบไฟล์ พอร์ตที่เปิดเผย ฯลฯ และเปลี่ยนเป็นไฟล์อิมเมจ Docker จากนั้นคุณสามารถแชร์ไฟล์ภาพกับทุกคนที่ต้องการเรียกใช้แอปพลิเคชันนั้น

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

$สัมผัสDockerfile

เปิดด้วยโปรแกรมแก้ไขข้อความที่คุณชื่นชอบ แล้วเขียนบรรทัดต่อไปนี้ลงไป:

ตั้งแต่เริ่มต้น
เพิ่ม สวัสดี/
CMD['/สวัสดี']

เกา ไม่ใช่ภาพหลัก แต่เป็นการบ่งชี้ว่า Docker ไม่ได้สร้างรูปภาพทับซ้อนกับรูปภาพอื่น มันถูกสร้างขึ้นจากรอยขีดข่วน คำสั่ง ADD จะนำไบนารีสแตติกที่ชื่อ |_+_|จากไดเร็กทอรีปัจจุบัน และเพิ่มลงในไดเร็กทอรีรากของไฟล์รูปภาพ เมื่อเราเรียกใช้คอนเทนเนอร์ตามอิมเมจนี้ ไฟล์เรียกทำงานของ hello จะปรากฏในไดเร็กทอรีรากเองที่ |_+_|

สุดท้าย บรรทัด CMD มีสตริง /สวัสดี สตริงนี้จะถูกดำเนินการเป็นคำสั่งเชลล์ทุกครั้งที่มีการสร้างคอนเทนเนอร์จากภาพนี้ ดังนั้นไฟล์ไบนารีที่เราเพิ่มลงในคอนเทนเนอร์ของเราและพิมพ์ข้อความที่เราเขียนในแอปของเรา

มาสร้างภาพโดยเรียกใช้ นักเทียบท่า build คำสั่งที่จะผ่านเนื้อหาของ Dockerfile และสร้างภาพ รันคำสั่งต่อไปนี้ในไดเร็กทอรีเดียวกันกับ Dockerfile และไบนารีที่เรียกใช้งานได้

$นักเทียบท่า build--tagสวัสดี .

NS -แท็ก สวัสดี ธงตั้งชื่อภาพเป็น สวัสดี และจุด ( . ) ในตอนท้ายบอก นักเทียบท่า build เพื่อค้นหาไดเร็กทอรีปัจจุบันสำหรับ Dockerfile และเนื้อหาที่เกี่ยวข้อง

การรันคอนเทนเนอร์ Docker

หากต้องการตรวจสอบว่ารูปภาพที่เราเพิ่งสร้างแสดงอยู่ในรายการรูปภาพหรือไม่ ให้เรียกใช้:

$ภาพนักเทียบท่า

สังเกตว่าภาพสวัสดีมีขนาดเล็กเพียงใดเมื่อเปรียบเทียบกับภาพอื่น ไม่ว่าในกรณีใดก็พร้อมที่จะเรียกใช้เป็นคอนเทนเนอร์

$นักเทียบท่าวิ่งสวัสดี

แค่นั้นแหละ! คุณสร้างคอนเทนเนอร์มินิมัลลิสต์ชิ้นแรกของคุณตั้งแต่เริ่มต้น

ตัวเลือกอื่น

แม้ว่าการสร้างรูปภาพจากศูนย์จะเป็นทางเลือกหนึ่งเสมอ ตัวอย่างเช่น รูปภาพอย่างอัลไพน์และ busybox เป็นสภาพแวดล้อมที่เบามาก โดยมีไลบรารี่ขนาดเล็ก เช่น musl แทนที่จะเป็น glibc

ใช้พวกเขาเป็นภาพหลักของคุณโดยใช้ จากอัลไพน์:ล่าสุด จะส่งผลให้ภาพมีขนาดเล็กลงเช่นกัน เนื่องจากภาพฐานมีขนาดเพียง 2-5 MB แจ้งให้เราทราบหากมีหัวข้อที่เกี่ยวข้องกับ Docker ที่คุณอาจต้องการให้เราพูดถึงต่อไป สามารถติดต่อได้ที่ ทวิตเตอร์ , Facebook หรือสมัครสมาชิกกับเราผ่านทางอีเมล์