ณ ตอนนี้ Docker เป็น Engine ที่ทำงานบน OS Linux
เท่านั้น แต่ไม่ต้องตกใจครับ เราสามารถติดตั้ง Docker ลงบน OS
อื่นๆเพื่อใช้งาน Docker ได้เช่นกัน แล้วทำไมผมต้องย้ำว่า Docker ทำงานบน
OS Linux เท่านั้น สาเหตุก็เพราะว่ากระบวนการทำงานมันแตกต่างกัน
ซึ่งเราควรจะเข้าใจพื้นฐานตรงนี้ก่อนครับ
เพราะเมื่อลงลึกไปแล้วจะได้ไม่งงกับการทำงานของมัน
ภาพทางด้านซ้ายเป็นสภาพแวดล้อมของ Docker
ขณะที่เราใช้งานมันบน OS Linux ครับ ไม่ว่าจะเป็นการเรียกใช้งานผ่าน
Command Line โดยตรงหรือผ่าน SSH ก็ตาม
Docker Host หมายถึง OS ที่ติดตั้ง Docker พูดง่ายๆก็คือ OS หลักของเครื่องที่เป็น Linux นั่นเอง
Docker client หมายถึง ตัวที่รับคำสั่งจาก Command Line ของเราเพื่อสั่งให้ Docker deamon ทำงานอีกทอดนึง
Docker deamon หมายถึง ตัวที่ควบคุม Container ทั้งหมด
ซึ่งรับคำสั่งจาก Docker client นั่นเอง
โดยปกติเราจะไม่ค่อยลงมายุ่งในระดับนี้โดยตรงนอกจากต้องการอะไรที่มัน
Hardcore จริงๆ
ภาพที่สองนี้คือสภาพแวดล้อมที่ Docker
ทำงานบน OS อื่นๆที่ไม่ใช่ Linux
เราจะสังเกตได้ว่าในท้ายที่สุดเราก็ต้องจำลอง Linux ขึ้นมาเพื่อรัน Docker
อยู่ดี แต่ขอบอกว่า “It’s not a bug, it’s a feature” 555+
เพราะนี่คือหลักการที่ทำให้ Docker คง Environment ของ Container
ไว้เหมือนเดิมได้ไม่ว่าเราจะสั่งการมันจาก OS ไหน และเป็นเหตุผลที่ว่าทำไม
Docker images ถึงมีแต่ Application บน Linux เท่านั้น
กลับมาที่ภาพ เราจะเห็นว่าการทำงาน Docker บน OS
อื่นๆคอนเซปไม่ต่างไปจากเดิมเลย สิ่งที่แตกต่างมีเพียงจุดเดียวคือ Docker
client ที่เปลี่ยนไปตาม OS เช่นเมื่อมันอยู่บน Windows ก็จะเป็นไฟล์
Docker.exe เป็นต้นครับ การทำงานที่เหลือก็คือ Docker client รับคำสั่งจาก
Command Line ของเราและส่งต่อไปยัง Docker deamon เพื่อให้ควบคุม Container
ต่อไป ภาพนี้ยังให้เราเห็นถึงวัตถุประสงค์และเหตุผลที่ Docker deamon
ต้องมากั้นระหว่าง Docker client กับ Container ด้วย นั่นก็เพื่อแปลง API
ที่ได้รับจาก OS ที่หลากหลายไปเป็น Command บน Linux นั่นเอง
การติดตั้งฉบับวิถีชาวโลก
เกริ่นมายาวมากเพิ่งจะเข้าเรื่องการติดตั้ง
555+ ในการติดตั้ง Docker ตามวิถีชาวโลกนั้น เป็นอะไรที่ง่ายมาก
ง่ายจนอาจทำให้เราไม่เข้าใจการทำงานของมัน ผลคือแอบไปนั่งงงอีก 2-3
ตลบว่าทำไมมันเกิดปัญหาแบบนั้นแบบนี้ แต่ ณ
จุดนี้เราเข้าใจการทำงานของมันแล้ว ฉะนั้นเพื่อไม่เป็นการเสียเวลา
เราสามารถ
ดาวน์โหลด Docker จากเว็บหลักและติดตั้งตามขั้นตอนได้เลย ไม่มีอะไรซับซ้อนครับ (
OS X,
Windows) หรือหากไม่เก่งอังกฤษก็มีบทความในไทยที่เขียนวิธีติดตั้งไว้แล้วมากมายเช่น
http://www.siamhtml.com/getting-started-with-docker/ (ผมไม่อยากทำงานซ้ำซ้อนและต้นทางเขาอธิบายไว้ดีมากอยู่แล้วเลยขอข้ามจุดนี้ไปนะครับ)
การทำงาน: หลังจากติดตั้งเสร็จเราจะได้
Docker Toolbox terminal พร้อมทั้ง Kitematic อยู่บน Desktop (และมี
VirtualBox + Git แถมให้ด้วยสำหรับคนที่ยังไม่เคยติดตั้ง) เมื่อเราเปิด
“Docker Toolbox terminal” ขึ้นมามันจะไปเรียก Bash Script
ตัวนึงเพื่อสั่งให้ VirtualBox เริ่มจำลอง Linux OS ที่ชื่อว่า boot2docker
ครับ (boot2docker เป็น OS Linux ที่เล็กมากเหมาะสำหรับไว้ใช้งาน Docker
ในเครื่อง Dev โดยเฉพาะ)
เมื่อเรารอสักพักจนมันติดตั้งอะไรเสร็จก็จะขึ้นรูปปลาวาฬ (ชื่อของมันคือ
MobyDock) นั่นหมายถึง Docker ในเครื่องเราพร้อมใช้งานแล้วครับ
การติดตั้งฉบับนอกตำรา
จริงๆแล้วหากใครอยากติดตั้งฉบับนอกตำราซึ่ง
หมายถึงมีแนวทางเป็นของตัวเองก็ทำได้เช่นกันครับ
เพราะเราเข้าใจการทำงานของมันแล้ว อย่างที่ผมใช้อยู่ในเครื่อง Dev คือจำลอง
Xubuntu ขึ้นมาเองใน VirtualBox และเรียกใช้งาน Docker ผ่าน Xubuntu โดยตรงใน Seamless Mode ครับ
จากภาพด้านบนจะเห็นว่า Desktop ผมเป็น Windows แต่ Terminal และ File
Manage เป็นของ Xubuntu นี่คือคุณสมบัติของ Seamless Mode ใน VirtualBox
ครับ เสมือนการ Merge 2 OS เข้าด้วยกันเลยทีเดียว
ผมสามารถเปิด Xubuntu Terminal แล้วสลับหน้าต่างไปมากับ Application
อื่นๆของ Windows ได้เสมือนมันอยู่ใน OS เดียวกันเลยครับ
เนื่องจากผมเติบโตมาในยุค GUI
ดังนั้นผมจะอุ่นใจมากหากอะไรๆมันจับต้องได้ครับ 555+
ซึ่งการติดตั้งแบบนี้เราสามารถทำทุกอย่างผ่าน GUI ของ Linux
ได้เลยไม่ว่าจะอ่าน แก้ไข ลบไฟล์ ดาวน์โหลด คอนฟิก
หรือแม้กระทั้งเปิดบราวเซอร์ในเครื่องโดยตรงเพื่อมาทดสอบเว็บ เป็นต้นครับ
ชีวิตสะดวกขึ้นเยอะมาก และอีกอย่างคือผมเป็นคนชอบจูนอะไรเองหมด
ซึ่งเป็นนิสัยที่เสียมาก
เหมือนซื้อของเล่นมาแล้วต้องรื้อเพื่อดูการทำงานของมัน
การที่ผมติดตั้งฉบับนอกตำราทำให้ผมเข้าใจ Docker อย่างลึกซึ้งครับ
(แต่เสียเวลาในการทำความเข้าใจมากเช่นกัน)
จุดประสงค์ของหัวข้อนี้แค่อยากให้เห็นภาพและแนวทางการติดตั้งนะครับ
ว่าเป็นไปได้หลากหลายและไม่ควรยึดติด
เราควรค้นพบทางที่ดีที่สุดของเราเองเพื่อความสุขในการทำงานครับ
ลองใช้งาน Docker กันดีกว่า
เพื่อเป็นการเริ่มต้นแบบง่ายๆผมจะพาเริ่มใช้
งาน Docker แบบเบสิค เป้าหมายคือ เปิดเว็บด้วย IP ของ Linux (ที่อยู่ใน
VirtualBox ) แล้วแสดงผลได้ตามภาพครับ
โดยหัวข้อนี้จะเน้นความเข้าใจในเชิงภาพรวมก่อนนะครับจะได้ไม่ง่วง 555+
ส่วนเรื่องเชิงลึกเอาไว้บทความต่อๆไปครับ
1. เตรียมความพร้อม
เปิด “Docker Toolbox terminal”
ขึ้นมาเราจะพบกับเจ้า MobyDock และรายละเอียดต่างๆได้แก่ ชื่อ Machine
default และ IP 192.168.99.100 โดย IP
ที่แสดงตอนนี้ให้เราทดเก็บไว้ในใจเป็น
#1 ก่อนนะครับ (แต่ละคนอาจได้ไม่เหมือนกัน) เพราะจะได้เอาไปใช้ในขั้นตอนหลังๆ
2. เตรียมไฟล์เว็บไซต์
ก่อนอื่นเราจะสร้างไฟล์เว็บไซต์ของเราไว้ที่
~/web โดยจะใช้วิธี pull ไฟล์ลงมาจาก git เลยนะครับ จะได้ไม่เสียเวลา
|
|
mkdir ~/web
cd ~/web
git clone https://github.com/jaynarol-blog/docker-tutorial-mobydock.git .
|
หลังจากพิมพ์คำสั่งไปแล้ว ให้เราลองพิมพ์คำสั่ง
ls จะพบว่าในโฟลเดอร์
~/web ของเรามีไฟล์
index.html และ mobydock.png เข้ามาแล้วครับ เสร็จขั้นตอนที่ 2
3. ดาวน์โหลด Docker image
ในขั้นตอนนี้เราจะดาวน์โหลด web server และทำความรู้จักกับ Docker image
ครับ ผมเลือกใช้ Docker image ที่ชื่อว่า Nginx ซึ่งมันก็คือ Application
Nginx ที่ถูกปรับแต่ง จูน ยำๆ จนมาอยู่ในรูปแบบ Docker image นั่นเอง ใน
Docker เราสามารถโหลดมันมาเก็บไว้ในเครื่องด้วยคำสั่ง
หลังจากเรารันคำสั่ง ผลคือ Docker จะไปค้นหา Docker image ที่ชื่อว่า
nginx ที่ Docker Hub และโหลดลงมาให้เราครับ
เราสามารถเลือกเวอร์ชั่นที่ต้องการด้วยการกำกับ tag ลงไปกับชื่อ
เช่น nginx:1.9 หมายถึง nginx เวอร์ชั่น 1.9 และหากเราไม่กำหนด tag หรือ
กำหนดว่า nginx:latest นั่นหมายถึงให้เอาเวอร์ชั่นล่าสุดครับ
4. รัน Container
ในขั้นตอนนี้เราจะติดตั้ง web server เพื่อให้มันเริ่มทำงานและทำความรู้จักกับ Docker container ครับ
|
|
docker run --name hellomobydock -v ~/web:/usr/share/nginx/html:ro -p 80:80 -d nginx:1.9
|
หลังจากเรารันคำสั่ง ผลคือ Docker จะสร้างสภาพแวดล้อมเสมือนการจำลอง OS
Linux ขึ้นมาใหม่ สำหรับรัน Application นี้โดยเฉพาะ เราเรียกมันว่า
Container ซึ่ง Container จะอยู่ในเครื่อง Linux
ตามที่ผมได้อธิบายไปเมื่อต้นบทความครับ จากนั้น Docker
ก็จะติดตั้งไฟล์และทำงานตามคำสั่งที่คนสร้าง Docker image ได้กำหนดไว้ครับ
โดยเพื่อความง่ายในการเข้าใจผมจะแยก Command ออกเป็นชุดๆและอธิบายดังนี้
-
docker run เป็นคำสั่งที่สั่งให้ docker สร้าง Container
-
--name hellomobydock เป็นการกำหนดให้
Container นี้ชื่อว่า hellomobydock
การตั้งชื่อเป็นทางเลือกจะตั้งหรือไม่ก็ได้ครับ
ถ้ามีชื่อเราก็อ้างอิงได้ง่ายขึ้นแต่ถ้าไม่มีก็ใช้ CONTAINER ID แทนได้
-
-v ~/web:/usr/share/nginx/html:ro เป็นการสร้างประตูมิติ (Volume) ให้กับ Container (ข้อมูลจะถูกแบ่งด้วย colon:
) โดยด้านซ้ายคือ path ในเครื่องของเรา และด้านขวาคือ path ใน Container
ครับ ตัวอย่างเช่น Container ของ nginx
จะอ่านไฟล์เว็บที่ /usr/share/nginx/html (ซึ่งโฟลเดอร์นี้อยู่ใน Container
อีกชั้นนึง) แต่ไฟล์เว็บของเราอยู่ข้างนอก Container เราจึงต้องผูก ~/web
เข้ากับ /usr/share/nginx/html ครับ จากนี้เมื่อ nginx
อ่าน/เขียนไฟล์ที่ /usr/share/nginx/html ก็จะเป็นการทำงานที่ ~/web
แทนครับ เหมือนประตูมิติ ส่วนตรง :ro เป็น optional ใช้ระบุว่าให้ อ่านเท่านั้น (read only)
-
-p 80:80 เป็นการผูก Port
ที่เชื่อมกันระหว่าง Linux และ Container ด้านซ้ายคือ port ใน Linux และ
ด้านขวาคือ port ใน Container เนื่องจากใน Container แต่ละตัวจะเหมือน OS
ที่มีสภาพแวดล้อมแยกออกมาต่างหากเพราะฉะนั้นเขาจะมี Port เป็นของตัวเอง
การที่เราผูก Port 80:80 นั่นหมายถึงถ้าใช้งาน port 80 บน Linux
เมื่อไหร่ให้ทะลุไปทำงานยัง Container นี้ที่ port 80 โดยอัตโนมัติ (port
80 บน Container nginx คือ web server)
-
-d เป็นการบอกให้ Container
ทำงานในเบื่องหลัง ถ้าไม่มีคำสั่งนี้ เราจะเห็นการทำงานของ Container ผ่าน
Console ทันที ซึ่งเมื่อปิด Console จึงหมายถึงการหยุด Container
เช่นกันครับ การสั่งให้มันทำงานเบื่องหลังทำให้ไม่ส่งผลกระทบเมื่อเราปิด
Console ลงไป
-
nginx:1.9 เป็นการบอกชื่อ image และ tag ที่ต้องการสร้างเป็น Container
เราสามารถตรวจสอบ Container ทั้งหมดที่กำลังทำงานอยู่ด้วยคำสั่ง
docker ps ครับ จากภาพจะเห็นว่า มี Container 1 ตัวทำงานอยู่ ซึ่งก็คือ hellomobydock ที่เราสั่งรันไปเมื่อสักครู่นั่นเองครับ
แถมอีกนิดกับคำสั่งของ Container ที่ใช้บ่อยๆ
docker ps ดู Container ทั้งหมดเฉพาะที่กำลังทำงานอยู่ เอาไว้ใช้ดู CONTAINER_ID ได้ด้วยครับ
docker ps -a ดู Container ทั้งหมดรวมถึงตัวที่ stop pause หรือทำงานเสร็จแล้ว
docker stop CONTAINER_ID หยุดการทำงาน Container
docker start CONTAINER_ID เริ่มการทำงาน Container
docker rm CONTAINER_ID ลบ Container (ต้อง stop หรือ kill ก่อน)
docker inspect CONTAINER_ID ดูข้อมูล Container อย่างละเอียด
docker logs CONTAINER_ID ดูข้อมูลการทำงานของ Container
docker exec -it CONTAINER_ID bash เข้าไปที่เครื่อง Container (เหมือน SSH เข้าไป)
ขอย้ำตรงนี้อีกครั้งนะครับ
เราจะไม่สามารถเข้าใจภาคปฎิบัติได้เลยหากไม่ได้ลงมือทำ ดังนั้น
ใครที่งงตรงไหนขอให้ลองเล่นดูแล้วจะเข้าใจเองครับ 🙂
5. แสดงผล
มาถึงขั้นตอนนี้ให้เอา
#1
ที่ทดไว้ในตั้งแต่ขั้นตอนที่ 1 ออกมาใช้ครับ อย่างของผมจะเป็น
192.168.99.100 ก็ให้เอา IP นี้ไปเปิดบน Browser
จะพบว่าสามารถเข้าเว็บได้แล้ว
สาเหตุที่เราเปิดเว็บได้เพราะว่า 192.168.99.100 คือ IP เครื่อง Linux
ของเรา เมื่อเราเรียกผ่าน http จะเป็นการเรียกใช้งาน port 80 โดยอัตโนมัติ
จากนั้นเมื่อ Linux ได้รับข้อมูลว่ามีการเรียกใช้งาน port 80 เจ้า Docker
ก็จะไปตรวจสอบว่า port นี้ได้ผูกกับ Container ไหนไว้หรือไม่ ซึ่งก็จะพบ
Container hellomobydock ของเราที่ผูก port 80 ไว้จึงส่งต่อข้อมูลเข้าไปยัง
port 80 ของ Container ตัวนั้น ส่งผลให้ nginx ที่รออยู่ทำงาน
และแสดงผลออกมาเป็น html นั้นเอง
6. ทำความสะอาด
หลังจากเราเล่นจนพอใจแล้วขั้นตอนสุดท้ายคือ
การทำความสะอาดให้เสมือนไม่มีอะไรเกิดขึ้น
ซึ่งในทางเทคนิคเรียกว่าการย้อนกระบวนการ
จุดนี้ก็สำคัญมากอาจช่วยให้เราเข้าใจมันมากขึ้นได้ครับ
ขั้นตอนแรกเราจะสั่งให้ Container หยุดทำงานก่อนด้วยคำสั่ง
|
|
docker stop hellomobydock
|
ถึงขั้นตอนนี้เมื่อเราใช้คำสั่ง
docker ps จะไม่เห็น
Container ทำงานอยู่แล้ว
และเมื่อเปิดเว็บก็จะเข้าไม่ได้แล้วด้วยเพราะมันหยุดทำงานแล้วนั่นเอง
แต่มันยังไม่หายไปไหนครับถ้าเราใช้คำสั่ง
docker ps -a จะพบว่ามันยังมีชีวิตอยู่ (แค่ไม่ได้กำลังทำงาน) ดังนั้น ณ จุดนี้เราสามารถสั่งให้มันกลับมาทำงานอีกครั้งได้ด้วยคำสั่ง
docker start hellomobydock ครับ
เมื่อเราเปิด-ปิดและเล่นมันจนพอใจ ถ้าเราอยากจะลบมันจริงๆแบบถาวร เราสามารถใช้คำสั่ง (ต้อง stop container ก่อนเท่านั้นถึงจะลบได้)
ถึงตอนนี้หากเราลองใช้คำสั่ง
docker ps -a จะไม่พบมันอีกแล้ว
ตอนนี้ Container เราสะอาดแล้วครับ ต่อไปเราจะทำความสะอาด Docker image บ้าง ก่อนอื่นให้เราใช้คำสั่ง
docker images เพื่อดูว่าในเครื่องเราตอนนี้มี images อะไรอยู่แล้วบ้าง และเพื่อเอา IMAGE ID สำหรับมาใช้ในคำสั่งลบ นั่นเอง
จากภาพจะเห็นว่า IMAGE ID ของ nginx:1.9 ในเครื่องผมคือ eb4a127a1188 ดังนั้นผมสามารถลบมันได้ด้วยคำสั่งนี้
มี trick เล็กน้อยคือเราสามารถใช้ IMAGE ID เพียง 2 ตัวหรือ 4
ตัวก็ได้ไม่จำเป็นต้องพิมพ์หมด แต่ระวังมันจะไปซ้ำกับตัวอื่นครับ
อีกทางคือเราสามารถใช้ชื่อ repo:tag เพื่อสั่งลบก็ได้เช่นกัน เช่น
docker rmi nginx:1.9 ครับ
มาถึงตอนนี้เครื่อง Linux ที่อยู่ใน VM เราสะอาดเหมือนใหม่แล้วครับ แต่ในเครื่องหลักของเรายังไม่เสร็จเพราะยังมีไฟล์ค้างอยู่ที่
~/web เราสามารถใช้คำสั่ง
rm -rf ~/web เพื่อสั่งลบได้เลย หรือใครอยากชัวก็ใช้คำสั่ง
cd ~/web ครับ แล้วสังเกตตรง title bar ของ Console นั่นคือที่อยู่ของไฟล์ที่มันอยู่ในเครื่องเรานั่นเอง
อย่างของผม /c/Users/Jaynarol/web ก็คือ C:/Users/Jaynarol/web ครับ สามารถเข้าไปลบล้างบางมันได้ตามสบาย
เสร็จสิ้นขั้นตอนทั้งหมดครับ ตอนนี้เครื่องเราสะอาดเหมือนลง Docker
ใหม่ๆ เราสามารถวนกลับไปทำขั้นตอนที่ 1 ใหม่ได้เรื่อยๆ จนกว่าจะพอใจครับ