6 คะแนน โดย GN⁺ 2024-11-24 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Bocker เป็นโปรเจกต์ที่นำ Docker มาเขียนใหม่ด้วย Bash ประมาณ 100 บรรทัด โดยมี flow คล้าย Docker เช่น pull อิมเมจ, run คอนเทนเนอร์, ดู logs, commit และลบ
  • การรันต้องใช้ btrfs-progs, curl, iproute2, iptables, libcgroup-tools, util-linux 2.25.2 ขึ้นไป และ coreutils 7.5 ขึ้นไป อีกทั้งต้องมีไฟล์ซิสเต็ม btrfs ใต้ /var/bocker และการตั้งค่าเครือข่าย bridge0
  • ตัวอย่างใน README แสดง flow ตั้งแต่ pull อิมเมจ centos:7 แล้วรันคำสั่งในคอนเทนเนอร์ จากนั้น commit ผลของ yum install -y wget และตรวจสอบ /usr/bin/wget ในการรันครั้งถัดไป
  • Bocker รันด้วย root และเปลี่ยน network interface, routing table, firewall rules จึงแนะนำให้ รันใน virtual machine และไม่มีการรับประกันเกี่ยวกับความเสียหายที่อาจเกิดกับระบบ
  • ปัจจุบัน implement docker pull, images, ps, run, exec, logs, commit, rm/rmi, networking และ quota ที่อิงกับ CGroups แล้ว แต่ data volume, data volume container และ port forwarding ยังไม่ได้ implement

วัตถุประสงค์และขอบเขตของ Bocker

  • Bocker เป็นโปรเจกต์ที่นำ Docker มา implement ด้วย Bash ประมาณ 100 บรรทัด
  • README แสดง flow คำสั่งที่คล้าย Docker โดยอิงกับ Bash และครอบคลุมฟีเจอร์อย่างการจัดการอิมเมจ, การรันคอนเทนเนอร์, การดู logs, การ commit การเปลี่ยนแปลง และการจำกัดทรัพยากร

ข้อกำหนดในการรัน

  • แพ็กเกจที่จำเป็นสำหรับการรันมีดังนี้
    • btrfs-progs

      • curl
      • iproute2
      • iptables
      • libcgroup-tools
      • util-linux 2.25.2 ขึ้นไป
      • coreutils 7.5 ขึ้นไป
      • ดิสโทรส่วนใหญ่ไม่มี util-linux ที่ใหม่พอ ดังนั้นอาจต้องดาวน์โหลด ซอร์ส util-linux 2.25 แล้วคอมไพล์เอง
      • ระบบต้องมีการตั้งค่าต่อไปนี้
      • ไฟล์ซิสเต็ม btrfs ที่เมานต์อยู่ใต้ /var/bocker
      • network bridge ชื่อ bridge0 พร้อม IP 10.0.0.1/24
      • เปิดใช้งาน IP forwarding ที่ /proc/sys/net/ipv4/ip_forward
      • การตั้งค่า firewall เพื่อ route traffic จาก bridge0 ไปยัง physical interface
      • มี Vagrantfile รวมมาให้เพื่อสร้าง environment ที่จำเป็นได้ง่าย

ข้อควรระวังเมื่อรัน

  • แม้จะมีข้อกำหนดครบถ้วน ก็ยังแนะนำให้รัน Bocker ใน virtual machine
  • Bocker รันด้วย root และต้องเปลี่ยนรายการต่อไปนี้
    • network interface
    • routing table
    • firewall rules
  • README ระบุชัดว่าไม่สามารถรับประกันได้ว่า Bocker จะไม่ทำให้ระบบเสียหาย

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

  • เมื่อดึงอิมเมจ centos:7 ด้วย bocker pull centos 7 จะได้ image ID เช่น img_42150
  • bocker images แสดง image ID และ source
    • ตัวอย่าง output: img_42150, centos:7
  • bocker run img_42150 cat /etc/centos-release แสดงข้อมูล release ของ CentOS จากในคอนเทนเนอร์
    • ตัวอย่าง output: CentOS Linux release 7.1.1503 (Core)
  • bocker ps แสดง container ID และคำสั่งที่รัน
  • bocker logs ps_42045 แสดง output log ของคอนเทนเนอร์นั้น
  • bocker rm ps_42045 ลบคอนเทนเนอร์
  • เมื่อรัน bocker run img_42150 which wget ในตอนแรก จะได้ผลว่าไม่มี wget
  • หลังติดตั้ง wget ด้วย bocker run img_42150 yum install -y wget แล้วใช้ bocker commit ps_42018 img_42150 เพื่อสะท้อนการเปลี่ยนแปลงกลับไปยังอิมเมจ
  • หลังจากนั้น bocker run img_42150 which wget จะแสดง /usr/bin/wget

การจำกัดทรัพยากรและ CGroups

  • ตัวอย่างการรัน Bocker แสดงให้เห็นว่าคอนเทนเนอร์ถูกวางไว้ใต้ CGroups
    • ใน /proc/1/cgroup จะมีรายการอย่าง memory:/ps_42152, cpuacct,cpu:/ps_42152 ปรากฏขึ้น
  • ตัวอย่างค่า CPU share และ memory limit เริ่มต้นมีดังนี้
    • /sys/fs/cgroup/cpu/ps_42152/cpu.shares: 512
    • /sys/fs/cgroup/memory/ps_42152/memory.limit_in_bytes: 512000000
  • สามารถเปลี่ยน resource limit ได้ด้วย environment variables
    • BOCKER_CPU_SHARE=1024
    • BOCKER_MEM_LIMIT=1024
  • ตัวอย่างหลังเปลี่ยนแสดงค่าดังนี้
    • CPU shares: 1024
    • memory limit: 1024000000

ฟีเจอร์ที่ implement แล้วและยังไม่ได้ implement

  • ฟีเจอร์ที่ implement แล้วในปัจจุบันมีดังนี้
    • docker build
    • docker pull
    • docker images
    • docker ps
    • docker run
    • docker exec
    • docker logs
    • docker commit
    • docker rm / docker rmi
    • Networking

      • รองรับ Quota / CGroups
      • bocker init ให้การ implement docker build แบบจำกัดมาก
      • ฟีเจอร์ที่ยังไม่ได้ implement มีดังนี้
      • Data Volume Containers
      • Data Volumes
      • Port Forwarding

ไลเซนส์

  • Bocker เป็นซอฟต์แวร์เสรีที่สามารถแจกจ่ายซ้ำและแก้ไขได้ภายใต้เงื่อนไขของ GNU General Public License
  • สามารถเลือกใช้ไลเซนส์เวอร์ชัน GPL v3 ที่เผยแพร่โดย Free Software Foundation หรือเวอร์ชันหลังจากนั้นได้
  • โปรแกรมถูกแจกจ่ายโดยหวังว่าจะเป็นประโยชน์ แต่ไม่มีการรับประกันโดยนัยใด ๆ เรื่องความสามารถในการขายหรือความเหมาะสมกับวัตถุประสงค์เฉพาะ

1 ความคิดเห็น

 
GN⁺ 2024-11-24
ความคิดเห็นจาก Hacker News
  • ผมเคยทำของคล้าย ๆ กันด้วย proot ชื่อว่า Bag [1] และคงไม่ได้อธิบายว่าเป็นทางเลือกแทน Docker
    มันไม่เกี่ยวกับ cgroups และอินเทอร์เฟซบรรทัดคำสั่งก็แตกต่างจาก Docker ด้วย เบื้องหลังคือผมสร้าง proxy chain ที่ดูเหมือนทราฟฟิก HTML ปกติ เพื่อหลบเลี่ยงการเซ็นเซอร์อินเทอร์เน็ตและ การตรวจสอบแพ็กเก็ตเชิงลึก และต้องให้มันรันต่อเนื่องได้ทุกที่ แต่ไม่อยากพอร์ตเป็นแอปเนทีฟบน Android
    ผมอยากรันบน Termux แต่ตอนนั้น Termux ไม่มี JDK/JRE และถ้าใช้ proot เปิดสภาพแวดล้อม Arch Linux ก็จะใช้ JDK ได้ สภาพแวดล้อม Arch ภายใน Termux โดยรวมมีประโยชน์กว่า และการสร้าง สภาพแวดล้อมแบบใช้ครั้งเดียว ที่ตั้งค่าต่างกัน ลบทิ้ง แล้วเข้าไปด้วย proot เพื่อรันเพียงคำสั่งเดียว ก็ทำให้เป็นอัตโนมัติด้วยสคริปต์ได้ง่าย ดังนั้นจึงตั้งชื่อว่า bag.sh เพราะหมายถึงรูปแบบที่เล็กกว่าตู้คอนเทนเนอร์ขนส่งมาก
    น่าสนุกตรงที่ bag.sh ยังมีโรดแมป/TODO ที่ไม่ได้แตะมา 5 ปีเหลืออยู่ด้วย ส่วนใหญ่จัดบรรทัดไว้ที่ 40 คอลัมน์ เพราะเขียนบนหน้าจอมือถือและอยากดูโดยไม่ต้องเลื่อน
    [1]: https://github.com/hkoosha/bag

    • เรื่องแบบนี้น่าจะมีอยู่ไม่น้อย ผมเคยต้องแพ็กเกจหลายองค์ประกอบไว้ในสภาพแวดล้อมเดียวในสถานการณ์ที่ VM ไม่เหมาะ เลยใช้ chroot กับ deb-bootstrap แล้วทำตัวติดตั้งด้วย makeself
      ผมสร้าง Debian ขนาดเล็กไว้ใน /opt ที่ใส่ซอฟต์แวร์ที่จำเป็นและ dependency อย่าง MySQL ไว้ด้วย และมันทำงานได้ค่อนข้างดี ใช้กันจนบริษัทที่ผมทำให้ถูกซื้อกิจการราวปี 2016 พูดให้กว้างกว่านั้น ผมคิดว่าการลองทำเวอร์ชันหยาบ ๆ ของแอปพลิเคชันขนาดใหญ่ด้วยตัวเอง เป็นหนึ่งใน วิธีที่ดีที่สุด ในการเรียนรู้กลไกภายใน
    • ดูเหมือนสคริปต์จะพลาดเครื่องหมายอัญประกาศสำคัญไปสองสามจุด น่าจะลองรัน shellcheck ดู
      mkdir -p $(dirname "$2")
    • หมุนแท็บเล็ต 8 นิ้วเป็นแนวนอนแล้วแทบจะได้ประมาณ 80x22 ที่พออ่านได้จริง
      ถ้าจับคู่กับคีย์บอร์ด Bluetooth ราว 10 นิ้วที่ใส่กระเป๋าด้านในของแจ็กเก็ตหนังได้สบาย ๆ ต่อให้ออกจากบ้านโดยไม่มีกระเป๋า ก็ยังไปนั่งมุมหนึ่งในเบียร์การ์เดนใกล้ ๆ แล้วเขียนโค้ดได้ แถมยัง productive กว่าที่คิด อาจเพราะมันมีแรงเสียดทานมากกว่าโน้ตบุ๊กนิดหน่อยในการสลับไปหาสิ่งรบกวนตามปกติ เลยลงเอยด้วยการจิบเบียร์ไปพลาง จ้องโค้ดต่อไปพลาง
  • ผมชอบของแบบนี้ ชอบสิ่งที่ทำด้วย Bash แบบน้อยที่สุด มาตลอด
    ยังมี proof of concept ของ load balancer ภายในคลัสเตอร์ที่เขียนด้วย Bash 40 บรรทัด ซึ่งทำขึ้นในแฮกกาธอนที่จัดเพื่อโปรโมตอินฟราสตรัคเจอร์แบบกระจายอย่าง Docker, Mesos เมื่อประมาณ 10 ปีก่อน: https://github.com/cell-os/metal-cell/blob/master/discovery/...
    น่าจะหายไปแล้ว แต่เคยมีเครื่องมือส่งต่อจาก colo-to-cloud ที่ใช้ reverse SSH tunnel ซึ่งมี redundancy และความเป็นแบบกระจายด้วย ของแบบนี้มีการรวบรวมไว้ดีใน Shell Fu และที่อื่น ๆ: https://www.shell-fu.org/

    • shell-fu.org ยอดเยี่ยมมาก แต่ก็อยากเห็นคอมเมนต์จากผู้ใช้คนอื่น ๆ ด้วย
  • ความจริงที่ว่าส่วนใหญ่ของ Docker สามารถนำมาทำใหม่ได้ง่าย ๆ แบบนี้ คือปัญหาใหญ่ที่สุดที่บริษัท Docker เผชิญมาและยังเผชิญอยู่ เพราะโดยพื้นฐานแล้วมันใกล้เคียงกับ โค้ดกาว ที่เอาฟีเจอร์ของเคอร์เนลมาต่อเข้าด้วยกัน
    จุดที่ Docker เพิ่มคุณค่าจริง ๆ ไม่ใช่แค่ Docker Hub แต่คือ Docker for Windows และ Mac ประเด็นสำคัญคือประสบการณ์แบบบูรณาการนั้นดีกว่าการต้องไปจัดการ VirtualBox กับ Vagrant เองเพื่อรัน Docker บนเครื่องพัฒนามาก

    • Rancher Desktop ก็เป็นตัวเลือกที่ใช้งานได้จริงและฟรี หลังจาก Docker ใช้ไลเซนส์ใหม่ หลายที่รวมถึงที่ทำงานของผมก็ย้ายไปทางนั้น
      ส่วนตัวผมคิดว่าเวทมนตร์ที่แท้จริงของ Docker คือ รูปแบบอิมเมจ Docker/OCI วิธีที่มันจัดการแคชและการกระจายอิมเมจคอนเทนเนอร์ได้ยอดเยี่ยม และยังคงเป็นแกนหลักที่ทำให้เวิร์กโฟลว์แตกต่างจาก VM “ทั้งก้อน”
    • Docker Desktop บน Mac เป็นของยุ่งเหยิงที่มีข้อจำกัดมากและสิทธิ์ไม่พอ การใช้ Docker CLI กับ Colima บน Mac ก็ยังมีข้อจำกัดด้านสิทธิ์ แต่至少ก็เลี่ยงไลเซนส์ที่ไร้สาระกับ Docker GUI ได้
      บน Windows ใช้ Docker ใน WSL ได้ และทำงานได้ดีมาก ผมไม่ค่อยเข้าใจว่าทำไมต้องใช้ Docker Desktop
    • บน macOS ผมใช้แค่ Colima ซึ่งให้ประสบการณ์ที่ดีกว่ามากและเบากว่ามาก
    • ไม่ใช่เลย Docker ควรสร้าง PaaS อย่าง CloudRun, Render, Fly เป็นลำดับแรก แล้วขายแพง ๆ ให้บริษัทต่าง ๆ
      แต่กลับไปทำ Docker Swarm แบบครึ่ง ๆ กลาง ๆ ที่ทำงานได้ไม่น่าเชื่อถือจริง ๆ แล้วก็ถูก Kubernetes แซงอย่างรวดเร็ว
    • ในบรรดาระบบที่เป็นที่นิยมและทำเงินได้ มีหลายอย่างที่ทำใหม่ได้ “ง่าย ๆ” ผมเคยคิดว่าคุณค่าของ Docker อยู่ที่ อิมเมจ Docker และก็เหมือนว่า Docker ถูกใช้ในแบบนั้นจริง ๆ
      วิธีที่ผมใช้มีแค่เอาสภาพแวดล้อม build เสมือนของใครสักคนมาใช้เพื่อ build ซอฟต์แวร์เมื่อหลายปีก่อนเท่านั้น
  • มีข้อความอย่าง “ยังไม่ได้ทำ”, “TODO”, “กำลังทำอยู่” อยู่ในรีโพ แล้วพอเห็นว่าคอมมิตล่าสุดคือหลายปีก่อนก็รู้สึกดี
    ทำให้สบายใจขึ้นนิดหน่อยกับการที่ไม่กลับไปดู TODO ที่โปรยไว้ทั่วโค้ดของตัวเอง ไม่ได้จะดูถูกผู้เขียนนะ แค่รู้สึกได้รับการปลอบใจ

    • เป็นประเด็นที่ดีเลย ไม่ใช่การดูถูกเลย แต่เป็นการทำให้สภาพแบบนี้กลายเป็นเรื่องปกติ ซึ่งดี
      ถ้ารู้สึกว่า ต้องทำ เพียงเพราะโค้ดที่ไม่ได้ค่าจ้าง เป็นอาสาสมัคร หรือทำเป็นงานอดิเรกถูกเผยแพร่อยู่ การเขียนโค้ดก็จะสนุกน้อยลง และอาจทำให้โค้ดที่เดิมทีจะเปิดเผยก็ไม่ถูกเผยแพร่ด้วย
    • รู้สึกว่าโปรเจกต์ส่วนใหญ่ หรือบางทีอาจทุกโปรเจกต์ ไม่มีวันจบ การ รู้ว่าเมื่อไรควรหยุด เป็นเรื่องสำคัญ
    • ผมว่าดีนะ บางอย่างอาจเสร็จสมบูรณ์ไปเลยก็ได้ และไม่จำเป็นต้องมีไอเดียถัดไปเต็มไปหมดเสมอไป แต่โดยปกติก็มักจะมีไอเดียถัดไปอยู่เสมอ
      ถ้ามีไอเดียถัดไปเสมอ ตามนิยามแล้วก็ย่อมมี TODO ที่ยังทำไม่เสร็จเหลืออยู่เสมอ จริง ๆ แล้ว สภาวะปกติ ของทุกโปรเจกต์ควรเป็นแบบนั้น
    • ตอนเริ่มโปรเจกต์ ควรใช้เวลาคิดถึง “สิ่งที่ไม่ใช่เป้าหมาย” หรือฟีเจอร์ที่นึกออกแต่ตั้งใจจะไม่ทำ
      การกำหนดขอบเขตให้ชัดเจนเป็นเรื่องที่โอเคเต็มที่และมักช่วยได้ เพราะจะได้ไม่ไล่ตามทางแยกย่อยจนโปรเจกต์รู้สึกเหมือน “ยังไม่เสร็จ” ไปตลอดกาล
    • ไม่เป็นไรเลย โปรแกรมทำสิ่งที่ผมต้องการ และเมื่อผมทำงานของตัวเองเสร็จ ผมก็หยุดพัฒนา ซอฟต์แวร์ไม่ใช่งานอดิเรกของผม
  • แปลกใจที่ยังไม่มีใครพูดถึง lazydocker ว่าเป็นทางเลือกที่ยอดเยี่ยมแทน Docker Desktop ใช้ได้บน Linux/macOS/Windows [1]
    เป็น เทอร์มินัล UI ที่ฟีเจอร์ค่อนข้างครบ และยังมีข้อดีที่สามารถรันผ่าน SSH ได้ด้วย
    [1] https://github.com/jesseduffield/lazydocker

    • เพิ่งขึ้นมาเมื่อไม่กี่วันก่อนนี่เอง: https://news.ycombinator.com/item?id=42214873
    • Lazydocker ดูน่าสนใจจริง ๆ แต่การมี โฆษณาโปรโมตตัวเอง สำหรับผลิตภัณฑ์คนละสายโดยสิ้นเชิงอยู่ใน README.md ของโปรเจกต์โอเพนซอร์สนี่ออกจะเกินไปหน่อย
      อย่างน้อยผมก็เพิ่งเคยเห็นแบบนี้ครั้งแรก ยังสงสัยด้วยว่าโฆษณาแบบนี้ได้รับอนุญาตตามข้อกำหนดการให้บริการหรือแนวนโยบายการใช้งานที่ยอมรับได้ของ GitHub หรือไม่
  • สงสัยว่าทำไม Bocker ถึงขึ้นหน้าแรกบ่อยขนาดนี้ ในปี 2024 Docker ยังเป็นประเด็นถกเถียงกันมากขนาดนั้นอยู่หรือ?
    ไม่เข้าใจว่าทำไมถึงไม่ยอมรับกันว่า Docker นำสิ่งที่มีประโยชน์จริง ๆ มาให้ โดยหลักคือ การเผยแพร่ซอฟต์แวร์ และการ “รันได้ง่ายทุกที่”

    • นี่เป็นแค่เครื่องมือเรียนรู้เพื่อดูว่า Docker ทำงานอย่างไร
      Docker เป็นการผสมผสานเทคโนโลยีเคอร์เนลที่มีอยู่แล้ว ได้แก่ namespace, cgroups, ระบบไฟล์แบบ union และอาจมีอย่างอื่นอีกสองสามอย่าง
    • เหตุผลที่ขึ้นหน้าแรกบ่อยคือมีคนจำนวนมากคิดว่า Docker เป็นสิ่งที่ซับซ้อนมาก แต่ในระดับพื้นฐานที่สุด จริง ๆ แล้วมันค่อนข้างสง่างามและเข้าใจได้
      เลยน่าสนใจ และแทบจะเป็นเรื่องสไตล์ HN ที่สมบูรณ์แบบ
    • อาจไม่ได้ขึ้นหน้าแรกเพื่อด้อยค่า Docker แต่เป็นเพราะคนเห็นว่า Docker มีประโยชน์และอยากรู้ว่า มันทำงานอย่างไร Bocker อาจเป็นประตูเข้าสู่เทคโนโลยีเหล่านั้นได้
    • ที่บริษัท ผมนำ overlayfs ไปแสดงเพื่อพยายามลดกระบวนการ CI ที่ยาวนาน และทุกคนก็ทึ่งกับความเร็วที่เพิ่มขึ้น
      หลังจากสาธิตให้หลายคนดู ผมถึงเพิ่งรู้ว่าพวกเขาอาจใช้ / ตรง ๆ ก็ได้ หรือไม่ก็ผมน่าจะเอา Docker ไปให้พวกเขาใช้ก็ได้เช่นกัน
  • มีสิ่งที่เหมือนพี่น้องต่างแม่อย่าง https://bastillebsd.org/
    Bastille ใช้ shell จัดการ FreeBSD jail ด้วยโครงสร้างหลายอย่างที่น่าจะเห็นได้ใน Docker มี dependency น้อยมาก เลยถูกใจมากกว่าซอฟต์แวร์จัดการ jail อื่น ๆ บน BSD

    • cbsd ก็น่าประทับใจพอสมควร: shttps://www.bsdstore.ru/en/about.html
      แต่แม้จะเป็นเครื่องมือแบบ CLI/TUI ก็เป็นโซลูชันที่ใกล้เคียงกับ “เกินจำเป็นขั้นสุด” ช่วงนี้ผมกำลังผ่านขั้นตอนสร้างและจัดการ jail ด้วยของที่มากับ FreeBSD ล้วน ๆ อยู่ แต่นี่เป็นแค่ช่วงชั่วคราวเท่านั้น
      ผมจะทำแบบนั้นจนกว่าภาพรวมว่าทุกอย่างประกอบกันอย่างไรจะฝังอยู่ในหัวมากพอจนมั่นใจในการดีบัก จากนั้นก็จะเลิกเอาหินมาเคาะกันเหมือนคนรู้ความ แล้วกลับไปใช้เครื่องมือระดับสูงกว่า
    • ใช่แล้ว สำหรับ shell script ประมาณ 100 บรรทัด มันเพิ่มคุณค่าได้มากทีเดียว
      แต่ผมใช้เวลาสักพักกว่าจะเข้าใจว่าทำไมถึงชื่อ Bastille La Bastille เป็นป้อมปราการที่สร้างขึ้นเพื่อป้องกัน Paris จากการโจมตีของอังกฤษในช่วงสงครามร้อยปี และต่อมาก็ถูกเปลี่ยนเป็นคุก
  • ส่วนที่ว่า “ดิสโทรส่วนใหญ่ไม่ได้ให้ util-linux เวอร์ชันใหม่พอ ดังนั้นน่าจะต้องเอาซอร์สจากที่นี่ไปคอมไพล์เอง” ต้องระวัง
    prefix ติดตั้งค่าเริ่มต้นคือ /usr/bin ดังนั้นกระบวนการติดตั้งอาจเขียนทับ คำสั่ง mount เดิมด้วยเวอร์ชันที่ต้องการไลบรารีซึ่งไม่มีอยู่จริงได้ แล้วตอนบูตครั้งถัดไป เคอร์เนลจะเมานต์ระบบไฟล์เป็นแบบอ่านอย่างเดียว

    • ควรเป็น /usr/local/bin
  • ไม่เหมาะสำหรับใช้ประจำวัน แต่ช่วยให้เห็นภาพว่า Docker คืออะไรและทำงานอย่างไร
    บน Linux นั้น Docker โดยพื้นฐานแล้วคือ chroot ที่แต่งตัวหรู

    • บน macOS/Windows และอื่น ๆ Docker โดยพื้นฐานแล้วคือ chroot ที่แต่งตัวหรูอยู่ใน Linux VM
  • เกร็ดน่าสนใจ: Docker เริ่มต้นด้วย Bash แล้วต่อมาย้ายไป Python ก่อนจะลงเอยที่ Go
    อีกอย่าง ในงาน Docker meetup ปี 2013 ก็มีคนเขียน โคลน Docker ด้วย Bash ด้วย ผู้คนอยากเรียนรู้ และหวังว่าสิ่งเหล่านี้จะช่วยได้