Jaynarol Blog

Docker : เทคนิคลับ Docker Toolbox

 

         บทความที่แล้ว Docker 2 : ติดตั้งและเริ่มใช้งาน (อย่างเข้าใจ) ผมพาเล่น Docker เล็กๆน้อยๆเพื่อให้เห็นภาพการทำงานของมัน นอกจากนี้ผมยังได้กล่าวถึงการติดตั้งฉบับนอกตำราซึ่งยกตัวอย่างติดตั้งในเครื่องผมไปพอสังเขป แต่ด้วยความที่ผมชอบลองผิดลองถูก “ทุกอย่างไม่มีคำว่าดีที่สุด มีแต่อยากจะหยุดรึยัง” ผมพยายามหาวิธีอย่างหนักที่จะให้การติดตั้งออกมาง่ายกว่าเดิมและก้าวข้ามข้อจำกัดต่างๆไปให้ได้

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

 

ทำไมต้อง Docker Toolbox

         การติดตั้ง Docker นั้นมีหลายรูปแบบและหลายเทคนิค สมัยก่อนผมมองว่า Docker Toolbox มีขีดจำกัดมากมาย เป็นเพียงของเล่นสำหรับมือใหม่ที่อยากลองใช้เท่านั้น การติดตั้ง Docker ของผมจึงซับซ้อนและใช้เวลาพอสมควรเพื่อให้ Docker ของผมใช้งานได้ตามเป้าหมายและก้าวข้ามขีดจำกัดต่างๆ ผมหลงทาง ผมกลับมาตระหนักได้ว่า เมื่อก่อนเราจำลอง WAMP หรือ  MAMP เราติดตั้งมันเสร็จได้ใน 1-2 นาทีก็พร้อมสำหรับทำงานแล้ว แต่ตอนนี้เราก้าวหน้าขึ้น รู้มากขึ้น แต่ทำไมชีวิตมันกลับลำบากกว่าเดิม เหตุนี้เองที่ทำให้ผมต้องถอยมานับ 1 ใหม่และมอง Docker Toolbox ในมุมที่ต่างออกไป เปลี่ยนจากการหาสิ่งใหม่เป็นใช้วิธีทะลายข้อจำกัดของมันไปทีละส่วนแทน ส่งผลให้ชีวิต ง่ายขึ้น อย่างมากจนรู้สึกได้ในหลายๆสถานการณ์ เช่น การลง OS ใหม่, การอัพเดทเวอร์ชั่น, การทำให้ทั้งทีมมีแนวคิดเดียวกัน, การนำไปสอน หรือแม้กระทั้งการเขียน Blog

ดังวลีที่ว่า Less is more

 

เทคนิคลับที่ 1 ย้าย ~/.docker ไว้ที่ปลอดภัย

นี่คือ 1 ในข้อจำกัดแรกที่ชวนผมหงุดหงิดไม่น้อยเพราะโฟลเดอร์ .docker ที่เก็บข้อมูลทุกอย่างที่เราใช้งาน Docker เอาไว้ เช่นพวก Key ต่างๆที่เชื่อมกับ Docker Machine และ ไฟล์ VM Boot2Docker สำหรับ Machine Default จะอยู่ที่ ~/.docker เสมอ ( ~/.docker ใน Windows คือ C:Users<Username> )

นิสัยของผมคือไม่ชอบเก็บข้อมูลสำคัญไว้ที่ Drive C เพราะเสี่ยงต่อการสูญหายมากหาก OS เสียหาย

ผมพยายามหาข้อมูลและวิธีข้ามข้อจำกัดนี้อย่างมาก จนสุดท้ายไปเจอวิธีนี้ ที่ง่ายและได้ผลอย่างน่าทึ่งคือการ Mount Link ~/.docker ไปไว้ที่อื่น ด้วยคำสั่งบน command line

 

 

<Username> คือชื่อ User ในเครื่องที่เราใช้งาน และ <Destination> คือชื่อโฟลเดอร์ปลายทางที่เราจะผูก เช่นของผม  mklink /J "C:/Users/Jaynarol/.docker" "D:/docker" เป็นต้น

คำสั่งนี้ใช้กับ Windows เท่านั้น สำหรับ Mac ผมไม่แน่ใจนะครับว่าเอาแนวคิดเดียวกันนี้ไปใช้ได้ไหม

หลังจากที่เราสร้างลิงค์เสร็จ ใน C:Users<Username>  ของเราจะมี shortcut ชื่อว่า .docker เมื่อเรากดเปิดมัน มันจะไปเปิดปลายทางที่เราผูกไว้ เทคนิคนี้เองทำให้เมื่อ Docker Terminal เขียนข้อมูลที่ ~/.docker มันจะไปเขียนที่ปลายทางแทนครับ เท่านี้เราก็หมดกังวลเรื่องความปลอดภัยของข้อมูลใน ~/.docker แล้วครับ

หมายเหตุ: การใช้คำสั่งนี้ได้ต้องไม่มีโฟลเดอร์ .docker อยู่ที่  C:Users<Username> นะครับ ให้ย้ายข้อมูลข้างในไปไว้ที่ปลายทางก่อนครับ

 

เทคนิคลับที่ 2 Mount Volume นอก ~/

โดยปกติ Docker Toolbox จะปรับแต่งให้เครื่องเราสามารถสร้างประตูมิติ (Volume) กับ Container ได้ทันทีเสมือนไม่มี VM มาเป็นตัวคั่นกลาง เช่น บทความที่แล้ว
docker run --name hellomobydock -v ~/web:/usr/share/nginx/html:ro -p 80:80 -d nginx:1.9
เราจะรู้สึกเหมือนว่า ~/web ในเครื่องของเรามันเชื่อมกับ /usr/share/nginx/html ของ Container โดยตรงเหมือน MyPC <1> Container ซึ่งจริงๆแล้วมันไม่ใช่ ในความจริงการเชื่อมต่อมีทั้งหมด 2 จุดคือ MyPC <1> VM <2> Container แต่ที่เราไม่รู้สึกว่าเราเชื่อมผ่าน VM เลย เพราะ Docker Toolbox ปรับแต่งมาให้เราแล้วนั้นเอง

เข้าเรื่องครับ ปัญหาของผมคือสิ่งที่ Docker Toolbox ปรับแต่งมาให้ รองรับการเชื่อมมิติ (Volume) กับข้อมูลที่อยู่ภายใต้ C:/Users/<Username> เท่านั้น หากข้อมูลผมอยู่ใน D:/project/001 จะไม่สามารถผูก Volume ไปที่ Container ได้ วิธีเดียวที่จะเชื่อมได้คือต้องเอาไฟล์ไปวางไว้ที่ C:/Users/<Username> ก่อนและ Run จากตรงนั้น และนิสัยเก่าผมที่ไม่ชอบเอาข้อมูลสำคัญไว้ Drive C ก็กำเริบทันที 555+ ผมหาวิธีอยู่พักนึงจนเข้าใจการทำงานของ Docker Toolbox ที่ปรับแต่งมาให้เราตอนแรก และก็ปรับแต่งใหม่ตามแนวทางของเรา ดังนี้ครับ

 

1 สร้างประตูที่ 1  = MyPC <> VM

เปิดโปรแกรม VirtualBox ขึ้นมาเราจะพบ VM ที่ชื่อ default ซึ่งคือตัวที่ Docker เราใช้ครับ จากนั้นกดขั้นตอนตามภาพ โดยจุดที่เราสนใจคือ Folder Path คือ โฟลเดอร์ที่เราเก็บโปรเจคของเราที่ต้องการผูก Volume และ Folder Name คือชื่อที่เราตั้งเอง จะเอาไว้ใช้ในขั้นตอนที่ 2 ครับ (แนะนำใหใส่ portal เหมือนผมครับจะได้ไม่งงเยอะ)

 

 

2 สร้างประตูที่ 2  = VM <> Container

1 – เราจะทำการแก้ไข start.sh เล็กน้อยเพื่อเพิ่มคำสั่งให้ VM ของเราสร้างประตูที่ 2 อัตโนมัติทุกครั้งที่เปิด Docker Terminal ขึ้นมา ใครที่ไม่ทราบว่า start.sh ของตัวเองอยู่ไหน ให้ดูได้จาก Properties ของ Docker Terminal ครับ

 

 

2 – แก้ไขไฟล์ start.sh โดยเพิ่ม 4 บรรทัดนี้ก่อนหน้าบรรทัด STEP="Finalize"


if [ "${VM}" == "default" ]; then
   "${DOCKER_MACHINE}" ssh "${VM}" "sudo mkdir -p /d/"
   "${DOCKER_MACHINE}" ssh "${VM}" "sudo mount -t vboxsf -o defaults,uid=\$(id -u docker),gid=\$(id -g docker) portal /d/"
fi

 

 

จุดสำคัญคืออย่าลืมเปลี่ยน /d/ เป็น Path จริงๆของตัวเองใน OS หลัก และกรณี Windows ต้องเปลี่ยนชื่อไดร์เป็น / ด้วยครับ เช่นของผม D:/ ก็จะเป็น /d/ หรืออีกตัวอย่าง E:/docker/project ก็เป็น /e/docker/project ครับ

อีกจุดคือเปลี่ยน portal เป็นชื่อ Folder Name ตามที่ได้ตั้งไว้ในขั้นตอนที่ 1 (ถ้าตั้ง portal ตามผมก็ใช้เหมือนเดิมได้เลย)

 

3 – หลังจาก save ไฟล์เรียบร้อย ให้เรา ปิด Docker Terminal > เปิด Docker Terminal ใหม่ และ ลองเข้าไปสำรวจใน VM ผ่าน docker-machine ssh อีกรอบ จะพบว่าโฟลเดอร์ของเราได้ถูกผูกเรียบร้อยครับ เป็นอันเสร็จสิ้นพร้อมใช้งาน

 

เพียงเท่านี้ จากนี้เราก็สามารถสั่ง Run Container โดยสามารถใช้ Volume เชื่อมกับโฟล์เดอร์บน Path ที่เราต้องการได้แล้วครับ

 

เทคนิคลับที่ 3 ไม่สนใจ IP

ในการใช้งาน Docker Toolbox บนเครื่อง บ่อยครั้งเราจะพบว่า IP มันเปลี่ยนไปตลอด เช่นเปิดมาครั้งแรก 192.168.99.100 วันดีคืนดีเปิดใหม่เป็น 192.168.99.101 ซะงั้น ดังนั้นเพื่อตัดปัญหานี้ เราจะใช้วิธี Map Port ครับ

 

 

จากภาพคือการเข้าไปตั้งค่าที่ VM ให้มันตรวจสอบการใช้งาน Port บน 127.0.0.1 (เครื่องของเรา) และส่งต่อข้อมูลไปยัง VM โดยอัตโนมัติ ส่งผลให้จากนี้หากเราใช้งาน Port นั้นบน 127.0.0.1 ก็จะทำงานบน VM แทนนั้นเอง อย่างในภาพผมเชื่อม Port 80 ไว้ เมื่อผมเปิดเว็บ http://127.0.0.1 บนเครื่องมันจะทำงานเหมือนผมเรียก http://192.168.99.100 ของ VM Docker เลยครับ ดังนั้นจากนี้ไปผมไม่ต้องกังวลแล้วว่า VM Docker เป็น IP อะไร ผมแค่เรียกผ่าน 127.0.0.1 ก็พอ เดี๋ยวมันทะลุไปให้เอง 🙂

 

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

http://127.0.0.1 => 192.168.99.100:80 (VM) => Nginx Contanier

127.0.0.1:3306 => 192.168.99.100:3306 (VM) => MySQL Contanier 1

127.0.0.1:33061 => 192.168.99.100:33061 (VM) => MySQL Contanier 2

 

 

เทคนิคลับที่ 4 จำลอง Domain เสมือน Server จริง

เทคนิคข้อนี้ต่อยอดมาจาก เทคนิคที่ 3 เมื่อเราทราบ IP ของ Docker ได้อย่างแม่นยำแล้วว่ามันคือ 127.0.0.1 ตลอด (จาก Port ที่ Map ไว้) เราก็ผูกโดเมนให้มันได้อย่างง่ายดายด้วยการแก้ไขไฟล์ hosts ในเครื่องของเราครับ

Windows: C:WindowsSystem32driversetchosts
OS X: /etc/hosts

 

 

จากนี้เมื่อเราเข้าเว็บด้วย http://www.site1.local ก็จะเป็นการเรียก 127.0.0.1:80 แล้วครับ

http://www.site1.local => 127.0.0.1:80 => 192.168.99.100:80 (VM) => Contanier

สามารถเอาไปประยุกต์ใช้ได้หลายท่าแล้วแต่โปรเจคเลยครับ

 

 

ปิดท้าย

จาก 4 เทคนิคนี้ช่วยให้ผมสามารถใช้ Docker มาเติมเต็มการทำงานทุกส่วน และสามารถใช้ Docker แทนการจำลองเดิมที่ผูกติดกับเครื่องได้อย่างเต็มรูปแบบ (เช่น WAMP)

ส่งผลให้ชีวิตผมง่ายขึ้นมาก เพราะสภาพแวดล้อมทุกอย่างเหมือน Production Server เป๊ะๆ จำลองได้แม้กระทั่งลองยิงผ่านโดเมนจริงๆเข้าไป และ การทำงานในทีมก็ไม่ต้องหวั่นว่า env จะไม่ตรงกันครับ ไม่ต้องมาคอยกังวลเรือง IP หรือ Port ต่างๆ อยากจพ Map อันโน้นเข้าอันนี้ ย้ายตรงนี้ไปตรงนั้น จับอะไรก็สะดวกไปหมดครับ ซึ่งผมคิดว่าหากผู้อ่านเข้าใจก็สามารถนำไปพลิกแพลงเป็นแนวทางและรูปแบบของตัวเองได้ไม่ยาก

ยังไงบทความนี้หากขาดตกบกพร่องตรงไหน รบกวนท้วงติงมาได้เลยครับ ผมยินดีปรับปรุงข้อมูลให้ถูกต้องที่สุด

และแน่นอนว่าหากท่านใดมีเทคนิคอื่นๆ ที่อยากเพิ่มเติม มาช่วยกันแชร์ได้ครับ ยินดีมากๆ

สวัสดีครับ