เป็น Virtualization จาก Server เครื่องนึง เราสามารถสร้าง Server จำลองได้หลายเครื่อง และใน Server จำลองแต่ละเครื่องสามารถลง OS และโปรแกรมต่างๆได้โดยไม่ไปกวนกัน (Conflict) ระบบส่วนใหญ่ในปัจจุบันจะย้ายมาเป็นแบบนี้เกือบทั้งหมดแล้ว (นอกจากบางงานที่ยังจำเป็นต้องใช้ Bare metal)
ในการใช้งานจริงเราจะมีเครื่อง Server หลายๆเครื่อง ไม่ได้มีเครื่องเดียวเหมือนในรูป ทุกเครื่องทำงานร่วมกันเป็น Cluster รายละเอียดส่วนนี้ขอเว้นไว้แค่นี้ ไม่งั้นจะนอกเรื่องไปไกลขึ้นอีก
แล้วมันดียังไง? แต่ละชุดของ App+Libs+Bins ไม่จำเป็นต้องรัน Guest OS ขึ้นมาโดยเฉพาะ แล้วเจ้า Guest OS เนี่ย จริงๆแล้วมันหนาเทอะทะมากกว่า Container Engine เยอะ พอมาใช้ Container เราจะสามารถรันหลายโปรแกรมที่เมื่อก่อนไม่สามารถรันในเครื่องเดียวกันได้ (Guest OS เดียวกัน)
ข้อดีอีกข้อคือ Container เนี่ยรันจาก Container Image (หลังจากนี้จะเรียกสั้นๆว่า Image) ซึ่งเป็นสิ่งเดียวกันตั้งแต่ครั้งแรกที่มันโดน Build + รันในเครื่องแรก + เครื่องสอง สาม สี่ห้า จนไปถึงเครื่อง Production ข้อดีข้อนี้จะทำให้ประโยคยอดฮิตกลายเป็นอดีต It works on my computer!
เริ่มเล่นละนะ
อารัมภบทมาซะเยิ่นยาว มาลองเริ่มเล่นกันซักที
ข้อหนึ่ง ลงโปรแกรม Docker Desktop โปรแกรมนี้ใช้ได้ทั้ง Mac และ Windows จากเว็บ Docker เอง โปรแกรมลงไม่ยาก ก็กดๆคลิกๆไปตามถนัดลงแล้วจะได้ icon ปลาวาฬแบกตู้ containers โผล่มาให้เห็น
เพิ่มเติมสำหรับคนที่ใช้ Windows Subsystem for Linux (WSL) สามารถใช้ Docker client ใน Linux ต่อเข้า Docker Desktop ที่รันใน Windows ได้ ใครไม่ใช้แบบนี้ ข้ามส่วนนี้ไปได้เลย
ขั้นแรก config ให้ Docker เปิดพอร์ตรอไว้เลย
สเต็ปสองก็ชี้ Docker Host ไปที่ Docker Desktop
export DOCKER=tcp://127.0.0.1:2375
สุดท้ายก็ลง Docker CLI สำหรับ Ubuntu ลงด้วยคำสั่ง
sudo apt-get install docker-ce-cli
ปิดท้ายด้วยคำสั่งพื้นฐานสำหรับ Docker
ถ้าเราคิดซะว่า Container เป็นเหมือน Virtual Machine (VM) เครื่องนึง คำสั่งที่เราต้องการก็ไม่มีอะไรมากไปว่า เปิด-ปิด-ต่อเข้าเครื่อง-ลบทิ้ง เพิ่มมาอีกนิดก็จะเป็น เปิด Firewall กับทำ Port Mapping ซึ่งเราอาจจะไม่ได้ทำใน VM
ส่วน Image ก็จะเหมือนการทำ Zip Archive หรือ ISO File แต่จะง่ายกว่า ซึ่ง Image จะทำเป็น Layer ตยช (ตัวอย่างเช่น) Layer C สร้างจาก Layer B (ซึ่งสร้างจาก Layer A อีกที) เรื่อง Image นี่เอาไว้เรามาว่ากันอีกที สำหรับตอนนี้ ลองใช้ Image ของคนอื่นไปก่อน (เหมือนกับที่เราไม่ได้สร้าง ISO File เอง แต่ดาวน์โหลด Ubuntu ISO มาใช้เพื่อลง Ubuntu Linux)
เปิดเครื่อง Web Server (Container)
$ docker container run -d nginx
ced7a1d474a10b6e4e0d2e23b47585d7772a481a6a8fd5b0b1aeca038b6ef05d
เรากำหนด -d เพื่อให้ Container รันด้านหลัง (Background/Detached) เราจะๆได้ ID เป็นชุด Hexadecimal Unique ID ชุดนึง ซึ่งเราสามารถเราไปใช้เลือกว่าจะสั่งงาน Container ไหนในตอนหลังได้
ดูรายชื่อ
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ced7a1d474a1 nginx “nginx -g ‘daemon of…” About a minute ago Up About a minute 80/tcp ecstatic_hertz
ถ้าเราลอง ls ดูจะไม่เห็น ecstatic_hertz แล้ว แต่จริงๆแล้ว ecstatic_hertz ยังอยู่ เราต้องเพิ่มพารามิเตอร์ -a เข้าไปแบบนี้ docker container ls -a จึงจะเห็นทุก Container รวมถึง Container ที่ซ่อนอยู่ด้วย
เปิดเครื่องพร้อมเปิด Firewall และทำ Port Mapping
$ docker container run -d -p 82:80 nginx
adbe9c6247cbb69a2493eb501178455c08f1b75ba32ab22ecd0abbf70b869619
เพิ่มพารามิเตอร์ -p 82:80 เพื่อจะ Map Port 82 ที่เครื่องของเราเข้าไปที่ Port 80 ของ Container ถ้าเรา docker container ls จะได้ข้อมูลเกี่ยวกับ Network แบบนี้ 0.0.0.0:82->80/tcp และถ้าจะ Map มากกว่าหนึ่ง Port เราสามารถกำหนด -p ได้หลายครั้ง
ถ้าเรามองว่า Container ก็เหมือน Mini VM ดังนั้น เราก็ควรจะลบ VM ที่เราไม่ได้ใช้ จะได้ไม่รก ถ้าจะลบหลายๆ Container เราสามารถใช้ ID หรือชื่อ ต่อๆกันไปตามที่ต้องการได้ หรือถ้าจะลบทุกๆ Container ที่หยุดทำงานไปแล้ว สามารถใช้คำสั่ง prune ได้
$ docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
84e245645e1e338a8e4fd70c95e964d5cf4c861d65ff33999adb5e8188e0a8d6
c8cc3a0e8ec9a0c0a4df10ef1c20d06a78c3c5c2625bad6f2d6257985b2a876d
b95ee9202ec4dff59c7fb658f304c042f4dc60536f98f17dd1535998e1d071d4
bde4f18ef33139e3f714b848ddc7bbf98f0fc58ae3f816f12bdae8b95f5543b8
Total reclaimed space: 27.38MB
แล้วถ้าจะ รัน Container ของ Ubuntu 20.04 ละ
$ docker container run -d ubuntu:20.04
7ecfa780a33541c7435ce385851084a4f9599f7cd8d602752254b5197274679e
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7ecfa780a335 ubuntu:20.04 "/bin/bash" 8 seconds ago Exited (0) 7 seconds ago quirky_clarke
$ docker container run -it ubuntu:20.04 bash
root@05b053dbc136:/# exit
exit
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS
05b053dbc136 ubuntu:20.04 "bash" About a minute ago Exited (0) About a minute ago heuristic_meitner