เขียนเรื่อง Docker คร่าวๆไว้เมื่อเดือนกรกฎาคมที่ผ่านมา ไม่ได้แนะนำการใช้งาน ครั้งนี้มาลงในรายละเอียดกันว่าจะเล่นอะไรได้บ้าง เนื้อหาของจะครอบคลุมดังนี้
- ติดตั้ง Docker
- ใช้งาน Docker เบื้องต้น
- สร้าง Image จาก Dockerfile
- ใช้ Hipache ทำ redirect + loadbalance ไปยัง Docker container
มาเริ่มจากการติดตั้งกันก่อน ใช้ Ubuntu 12.04 LTS เหมือนเดิม อัพเกรดให้เรียบร้อย จากนั้นมาติดตั้ง Docker กัน Docker ต้องใช้ kernel ที่มี cgroup ซึ่งใน Ubuntu 12.04 ในส่วนของ kernel ยังไม่มี cgroup เพราะฉะนั้นต้องอัพเกรด kernel และ reboot เครื่อง :)
apt-get update
apt-get upgrade
sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring
sudo reboot
หลังจาก reboot เครื่องเราก็จะได้ kernel ใหม่กันแล้ว มาเริ่มติดตั้ง Docker กันต่อได้
sudo sh -c "wget -qO- https://get.docker.io/gpg | apt-key add -"
sudo sh -c "echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
sudo apt-get update
sudo apt-get install lxc-docker
จากนั้น กำหนดให้ผู้ใช้อยู่ในกลุ่ม docker ดังนี้
sudo gpasswd -a <username> docker
sudo service docker restart
มาทดลองกัน โดยใช้คำสั่ง
docker run -i -t ubuntu /bin/bash
คุณจะพบว่า Docker จะทยอยดาวน์โหลด image และสั่ง run bash เป็น process หนึ่ง แล้ว Docker ก็จะพาคุณเข้าไปยัง container จะได้ shell prompt ดังนี้
คุณสามารถใช้คำสั่ง Linux ปกติได้ใน container โดยไม่มีผลกระทบใดๆ กับเครื่อง host ที่เราทำงานอยู่ มาลองคำสั่งที่ต้องใช้งานกันประจำกันก่อนดีกว่า ตอนนี้ docker run container จาก base image ที่ชื่อ ubuntu ให้คุณเปิด terminal ขึ้นมาอีก 1 หน้าต่างแล้วใช้คำสั่ง
docker ps
จะได้ผลลัพท์ออกมาแบบนี้
docker ps เป็นคำสั่งที่เอาไว้แสดงรายการ container ที่ทำงานอยู่ ในกรณีนี้เรามี container 1 ตัวที่กำลังทำงาน โดยกำลังทำงานโดยคำสั่ง /bin/bash นั่นเอง การจัดการกับ container ก็จะเหมือนกับการจัดการกับ virtual machine คุณสามารถสั่ง start, stop, run, kill ได้ด้วย
การใช้งาน Docker เราจะต้องมี Docker image ซึ่งการที่จะได้ image มานั้นมี 3 ช่องทางคือ
- สร้าง image จาก Dockerfile
- สั่ง pull, run เพื่อดาวน์โหลด image จาก Docker index
- สร้างจาก image ที่มีอยู่เดิม
เราจะเล่นวิธีง่ายๆ กันก่อน ลองใช้คำสั่ง docker search เพื่อค้นหา image ที่ต้องการ
docker search
ผลลัพท์ที่ได้ออกมาแบบนี้
เราจะพบว่ามี image ที่เกี่ยวข้องกับ wordpress เยอะมาก แลัวจะเลือกตัวไหนดี ? คำตอบง่ายๆ ก็คือเลือกตัวที่มี ดาวเยอะๆ และ TRUSTED ครับ ถ้าอยากดูรายละเอียดก็สามารถดูจากหน้าเว็บได้ที่ http://index.docker.ioครับ
ก็ลองค้นหา image กันได้ เมื่อได้ image แล้ว สั่งให้ download image wordpress มาไว้ที่เครื่องเราดังนี้
docker pull jbfink/wordpress
ลองสั่ง docker images เพื่อดูว่าเรามี image อะไรบ้าง
docker images
จะพบว่าเรามี image wordpress มาแล้ว ให้ลองสั่ง run พร้อมระบุเลข port ที่ต้องการ map เข้าไปใน container
docker run -d -p 80 -p 22 jbfink/wordpress
Docker จะคืน shell prompt มาให้เราพร้อม ID ของ container ลองใช้คำสั่ง logs เพื่อดูว่า container ทำงานอะไรไปแล้วบ้าง
docker logs 4216aa1cba8c
ในส่วน ID นี้สามารถระบุแบบเต็มหรือแบบย่อโดยพิมพ์ 3-4 ตัวอักษรแรกก็ได้ image นี้จะ random password ของ user, mysql root ฯลฯ มาให้ให้ลองดูจาก log เมื่อ container run เสร็จแล้วเราจะได้ port เลขยาวๆ map ไปยัง port ต่างๆ ของ container ให้ลองใช้คำสั่ง docker ps
ดู
ตามรายละเอียด คุณสามารถใช้คำสั่ง ssh เข้าไปใน container ได้โดยใช้ port 49153, Web Server ทำงานบน port 49154 ให้ลองเข้าเว็บตาม port ที่ Docker ระบุมาให้ ก็จะเข้าสู่หน้าติดตั้ง Wordpress ดังนี้ ตั้งค่านิดหน่อยคุณก็จะได้ Wordpress ใช้งานแล้ว :)
เอาพอสนุกสนาน ทีนี้มาลองสร้าง image กันบ้าง อย่างที่บอกข้างต้น เรามีวิธีการสร้าง image อยู่หลายวิธี แต่เบื้องหลังของการทำ image จะเป็นการสร้าง file system ซ้อนกันเป็น layer ดังนั้นเพื่อความสะดวก ตรวจสอบได้ง่าย ผมแนะนำให้สร้างจาก Dockerfile ครับ Dockerfile เป็น config เบื้องต้นสำหรับ image ที่เราต้องการสร้าง ซึ่งเราไม่จำเป็นต้องสร้างจาก base image ที่มีทั้ง service และ application เราจะใช้หลักการของ Docker ในเรื่อง filesystem layer เป็นตัวช่วย โดยดึง base image ที่เป็นระบบปฏิบัติการต่างๆ เอามาต่อยอดโดยการติดตั้ง service ที่เราต้องการลงไป ตั้งค่า config ต่างๆ และ expose port สำหรับเปิดให้ใช้งาน โครงสร้าง Dockerfile แบบง่ายๆ มีดังนี้
- FROM ระบุว่า image จาก base image ใด
- MAINTAINER ระบุชื่อของผู้ดูแล image นี้
- RUN สั่งให้ run คำสั่งที่ต้องการ เช่น apt-get install xxx และ commit image ทุกๆ ครั้งที่ใช้คำสั่งนี้
- EXPOSE เปิด port ที่ต้องการใช้งาน
- CMD ใช้คำสั่งบน command line
เพื่อความเข้าใจ มาลงมือสร้าง image กันดีกว่า ให้ clone project จาก github.com/anoochit/docker-apache2ดังนี้
git clone git@github.com:anoochit/docker-apache2.git
จากนั้นสั่ง build image ดังนี้
cd docker-apache2
docker build -t apache2 .
รอไปเรื่อยๆ จน build เสร็จ คุณจะได้ image ID ยาวๆ มา 1 ตัว
ลองใช้คำสั่ง docker images ดูก็จะพบว่าคุณมี image apache2 เพิ่มขึ้นมาแล้ว
ลองสั่ง run ดูครับ
docker run -d -p 80 apache2
ทีนี้ลองเปิด browser ดูครับว่า apache ทำงานมั๊ย อย่าลืมระบุ port นะครับ เราก็จะได้หน้าเว็บเปล่าๆ มาดังนี้
มาลองเล่นอะไรสนุกๆ กันอีกนิดหน่อย เราสามารถระบุ part ของเครื่อง host เพื่อ map ไปยัง directory ภายใน container ได้ ใน project ที่ clone มาจะมีไดเรคทอรี www อยู่ เอามาเล่นได้เลยครับ
WWW_DIR=`pwd`\www
docker run -d -p 80 -v $WWW_DIR:/var/www apache2
ทีนี้ลองเปิด browser ใหม่ เราจะได้หน้าเว็บอย่างนี้
มาลองเล่นอีกอย่างหนึ่ง กรณีที่คุณสร้าง image แล้วต้องการนำไปเผยแพร่บน Docker Index สามารถทำได้ 2 วิธีคือ
- สั่ง push image
- สั่งสร้างจาก github
ซึ่งทั้ง 2 กรณีนี้จะต้องเป็นสมาชิกของ Docker Index ก่อน ส่วนสร้าง image จาก GitHub สามารถเพิ่ม project ของคุณผ่านหน้าเว็บ Docker Index ได้เลย ซึ่งง่ายมาก แต่ในกรณีที่เราต้องการใช้งาน Docker Registry ของตัวเอง วิธีการง่ายๆ ดังนี้
- ตั้ง Docker Registry Server
- สั่ง push, pull ผ่าน Docker Registry ของตัวเอง
วิธีการง่ายๆ มีแค่นี้ ผมได้ตั้ง Docker Registry ของผมเองชื่อ registry.redex.net ทำงานบน port 5000 (default) สามารถสั่ง push และ pull image ได้ง่ายๆ ดังนี้ การ push image ไปยัง registry ให้ tag image id ที่คุณต้องการก่อน จากนั้นค่อยสั่ง push
docker tag 850607808486 registry.redex.net:5000/myweb
docker push registry.redex.net:5000/myweb
กรณีที่คุณอยู่ Host อื่นที่มี Docker ติดตั้งอยู่ คุณก็สามารถ pull image จาก Docker Registry มาใช้งานได้ ดังนี้
docker pull registry.redex.net:5000/myweb
ถ้าชื่อ image มันยาวไปก็สั่ง tag จาก image ID ได้ จากนั้นก็สั่ง run ได้ตามปกติ :)
docker tag a6f2023aa5f9 myweb
docker run -d -p 80 -p 22 myweb
มาลองทำ Load Balance กับ container แบบง่ายๆ กันดูบ้าง ที่เครื่อง host ติดตั้ง hipache และ redis server ให้เรียบร้อย หรือจะใช้ docker ก็ได้ครับ
docker run -d -p 6379:6379 -p 80:80 samalba:hipache supervisord -n
จากนั้นตั้งค่า Hipache ผ่าน Redis
redis-cli -h 172.17.42.1 -p 6379 rpush frontend:www.redex.net myweb
สั่ง run container เพิ่มสัก 2-3 ตัว ด้วยคำสั่ง
ID=$(docker run -d -p 80 -p 22 myweb)
PORT=$(sudo docker port $ID 80)
redis-cli -h 172.17.42.1 -p 6379 rpush frontend:www.redex.net http://172.17.42.1:$PORT
คำสั่งข้างต้น run container หา port ที่ผูกกับ port 80 แล้วลงทะเบียนใน redis จากนั้นใช้คำสั่ง
redis-cli -h 172.17.42.1 -p 6379 lrange frontend:www.redex.net 0 -1
ทีนี้มาลองทดสอบ Hipapche กัน อย่าลืมกำหนด DNS Record ให้เป็นแบบ Wildcard เพื่อให้ Hipache ทำ redirect ไปยังเว็บที่ถูกต้องให้ ให้ทดลองเปิด browser ดูแล้วลอง refresh หลายๆ รอบ จะได้ผลลัพท์ดังนี้
จะเห็นว่า Hipache พยายามทำ Load Balance ให้ด้วย สำหรับท่านที่สนใจ Hipache ก็หาข้อมูลเพิ่มเติมได้ที่ dotCloud