Docker คืออะไร ใช้งานอย่างไร

เรื่องมันมีอยู่ว่าผมได้เรียนวิชา Network Admin แล้วอาจารย์ก็ให้หัวข้อไปศึกษาของแต่ละคนมาแล้วผมก็จับได้ Docker น่ะ

Rachata Tongpagdee
7 min readMar 1, 2018

Docker คืออะไร

Docker คือ engine ตัวหนึ่งที่มีการทำงานในลักษณะจำลองสภาพแวดล้อมขึ้นมาบนเครื่อง server เพื่อใช้ในการ run service ที่ต้องการ มีการทำงานคล้ายคลึงกับ Virtual Machine เช่น VMWare, VirtualBox, XEN, KVM แต่ข้อแตกต่างที่ชัดเจนคือ Virtual Machine ที่รู้จักกันก่อนหน้านี้นั้น เป็นการจำลองทั้ง OS เพื่อใช้งานและหากต้องการใช้งาน service ใดๆ จึงทำการติดตั้งเพิ่มเติมบน OS นั้นๆ แต่สำหรับ docker แล้วจะใช้ container ในการจำลองสภาพแวดล้อมขึ้นมา เพื่อใช้งานสำหรับ 1 service ที่ต้องการใช้งานเท่านั้น โดยไม่ต้องมีส่วนของ OS เข้าไปเกี่ยวข้องเหมือน Virtual Machines อื่นๆ ตัวอย่างดังรูป

Docker นั้น เป็นที่รู้จักกันอย่างแพร่หลายในช่วง 1–2 ปีที่ผ่านมานี้ เนื่องจากสามารถใช้งานได้อย่างสะดวกและตอบสนองความต้องการของ ผู้พัฒนาโปรแกรม (Developer) หรือ ผู้ดูแลระบบ (System admin)

Docker image คืออะไร

Docker image เป็นเหมือนตัวต้นแบบของ container ซึ่งภายในจะประกอบด้วย application ต่างๆ ที่มีการติดตั้งไว้เพื่อใช้งานสำหรับ service นั้นๆ รวมทั้งมีการ config ค่าต่างๆ ไว้เรียบร้อยแล้ว จากนั้นก็นำมาสร้างเป็น docker image บน registry เพื่อนำใช้งาน ทั้งนี้ผู้ใช้งานสามารถยังสร้าง docker image สำหรับใช้งานเองได้อีกด้วย

Docker container คืออะไร

Docker container สามารถมองได้เสมือนกล่อง ซึ่งนำ docker image มาติดตั้ง เพื่อให้สามารถใช้งาน service ที่ต้องการจาก image นั้นๆ ได้ โดยใน container แต่ละตัวจะมีการใช้งาน RAM, CPU, ไฟล์ config ต่างๆ เป็นของแต่ละ container เอง และยังสามารถสั่ง start, stop ได้ที่ container นั้นๆ อีกด้วย

ความน่าสนใจของ docker

  • Docker engine สามารถใช้งานได้บนหลาย platform ทั้งบน Linux, Mac และ Windows
  • Docker มีขนาดเล็ก สามารถใช้งาน และติดตั้งได้อย่างรวดเร็ว และสะดวกในการ start / stop หรือแม้แต่การย้ายไปใช้งานสำหรับเครื่อง server อื่นที่มีการ run docker engine ก็สามารถทำได้โดยไม่ซับซ้อน
  • ผู้ใช้งาน docker ไม่จำเป็นต้องติดตั้ง OS อีกครั้งเพื่อติดตั้ง container รวมทั้งไม่จำเป็นต้อง config เพิ่มเติมในส่วนที่ไม่จำเป็นอีกด้วย
  • Docker มีความต้องการในการใช้ CPU, RAM และพื้นที่น้อยกว่า Virtual Machine ทั้งนี้ในทรัพยากรที่มีเท่ากัน docker สามารถใช้งาน container ได้มากกว่า Virtual Machine
  • เนื่องจากผู้ใช้งาน สามารถสร้าง docker image ได้เอง จาก dockerfile ดังนั้นการใช้งาน docker ยังช่วยลดปัญหาสภาพแวดล้อมที่ต่างกัน ที่มักพบเมื่อบาง application สามารถทำงานได้บน development server แต่ไม่สามารถใช้งานบน production server ได้
  • Docker ยังมี docker registry ซึ้งผู้ใช้งานสามารถเลือก pull image ต่างๆ ที่มีการสร้างไว้ให้แล้วมาใช้งาน โดยมี Docker Hub เป็น registry หลักในการเรียกใช้ image

ข้อดีของ Docker เมื่อเทียบกับ VMs

  • Docker ไม่ต้องเสียเวลาในสร้าง OS ใหม่ และการ config แต่ละ OS เลย
  • Docker เบาและเร็วกว่ามาก ไม่ว่าจะเป็น start stop และ restart เพราะมันใช้ OS, CPU และ RAM ร่วมกันกับ Host OS
  • Docker สามารถรัน container ได้มากกว่า VMs ในเครื่องที่มีทรัพยากรที่เท่ากัน
  • Docker มีระบบ Registry ทำให้สามารถเคลื่อนย้าย หรือติดตั้ง Container ได้สะดวก และรวดเร็วกว่ามาก
  • Containers มันรันอยู่บน Docker Engine ทำให้ไม่ต้องสนใจว่า Infrastructure หรือ Host OS ว่าจะเป็นอะไรยังไง ทำให้หมดปัญหาว่าเครื่อง Dev รันได้ แต่เครื่อง Production มันรันไม่ได้บ้าง หรือเครื่อง Dev แต่ละคนติดตั้งเครื่องมือคนละเวอร์ชันกัน เราก็ build container เป็น image แล้วส่งในคนในทีมใช้ ก็หมดปัญหาแล้ว

การติดตั้ง Docker

Docker สามารถติดตั้งได้ทั้ง Linux, Mac (OS X 10.11 or newer macOS)และ Windows (Windows 10 Pro 64bit) ซึ่งสำหรับ Mac และ Windows รุ่นต่ำกว่านั้นต้องติดตั้งโดยใช้ Docker Toolbox แทน โดยเราจะใช้ Docker Toolbox เนื่องจากผมใช้ window 8

ติดตั้ง Docker Toolbox

Docker Toolbox จะประกอบด้วย

  • Docker CLI client ไว้สำหรับรันคำสั่ง Docker Engine (docker) เพื่อสร้าง images และ containers
  • Docker Machine (docker-machine) เพื่อสร้าง Linux VM ตัวเล็กๆ ที่มี Docker Engine รันอยู่
  • Docker Compose สำหรับรันคำสั่ง docker-compose
  • Kitematic ที่เป็น Docker GUI
  • Docker QuickStart shell ที่มีการทำ preconfigured สำหรับ Docker command-line environment ไว้แล้ว
  • Oracle VM VirtualBox

Docker Concepts

Images

  • images จะเป็น read only templates ที่เอาไว้สร้าง containers
  • images จะสร้างโดยใช้คำสั่ง docker build ซึ่งใครๆ ก็สามารถสร้างได้
  • images นึงๆ จะประกอบด้วยชั้น (layer) ของ images อื่นๆ
  • images จะถูกเก็บไว้ที่ Docker registry

Containers

  • ถ้าเปรียบ images เป็น class แล้ว containers ก็จะเป็น instance ของ class นั้นๆ (runtime object)
  • containers จะถูกสร้างมาจาก images ซึ่งภายใน container จะมี binaries และ dependencies ทั้งหมดที่จำเป็นในการรันโปรแกรมที่ต้องการ

Registries and Repositories

  • registry คือที่ที่เอาไว้เก็บ images
  • เราสามารถสร้าง registry เองก็ได้ หรือจะใช้ public registry ของ Docker ที่ชื่อ DockerHub ก็ได้
หน้าตาของ Docker Hub
  • ภายใน registry จะมี repositories ที่เอาไว้จัดเก็บ images แต่ละตัว
  • Docker repository แต่ละอันคือที่รวบรวม images ตัวเดียวกัน แต่ต่างเวอร์ชัน แยกโดยใช้ tags

ลองสร้าง Hello World Docker Container

  • ให้เปิดเบราว์เซอร์ไปที่ https://hub.docker.com/ แล้วสมัครสมาชิกให้เรียบร้อยนะแล้วก็ และค้นหา busybox
  • เลือก repository ของ busybox ที่เป็น offical ข้างในจะแสดงรายละเอียดวิธีการใช้งาน https://hub.docker.com/_/busybox/
  • เปิด Docker Quickstart Terminal เปิดครั้งแรกก็รอก่อนนะครับมันจะ Initailize โปรแกรมแปบนึง
หน้าตาของ Docker Terminal
  • พิมพ์คำสั่ง docker images เพื่อดูรายการ images ทั้งหมดที่เรามี จะพบว่าตอนนี้ยังไม่ images ใดๆ
docker images
  • พิมพ์คำสั่ง docker run busybox echo "hello world"คำสั่งนี้เอาไว้สร้าง container จาก image ชื่อ busybox โดยปกติจะพิมพ์
docker run busybox:1.26.2 echo “hello world”

ที่ระบุ tag เป็น 1.26.2 (แต่ถ้าไม่ระบุ tag จะใส่ tag เป็น latest เสมอ) ซึ่งถ้าเรายังไม่มี image ตัวนี้ Docker จะทำการ pull มาจาก registry ให้ ตามด้วยคำสั่งที่จะใช้งานคือให้พิมพ์คำว่า hello world ออกมา รูปแบบคำสั่ง docker run repository:tag command [arguments] รายละเอียดเพิ่ม ที่นี่

  • การรัน Docker Container ใน interactive mode ทำได้โดยการใช้ -i flag และใช้ -t เพื่อสร้าง pseudo-TTY เพื่อแสดง input และ output ตัวอย่าง docker run -i -t busybox และลองสร้างไฟล์ a.txt ถ้าต้องการออกจากโหมดนี้ใช้คำสั่ง exit Docker จะ shutdown container นี้ไป
  • ถ้าลองรัน docker run -i -t busybox อีกรอบ และ ls ดูจะพบว่าไม่มีไฟล์ a.txt เนื่องจากทุกครั้งที่ใช้ docker run จะเป็นการสร้าง container ใหม่เสมอ

ใช้งาน Docker Container

  • รัน container ใน detached mode
  • การใช้คำสั่ง docker ps
  • การกำหนดชื่อ container
  • การใช้คำสั่ง docker inspect
  • การใช้งาน port
  • การใช้คำสั่ง docker logs

Detached Mode

ความแตกต่างระหว่างการรัน container แบบ foreground (default mode) กับแบบ background หรือ detached mode (-d option) คือ เมื่อรันแบบ foreground หน้าจอ console จะแสดง process ของ container ตัวนั้นๆ อยู่ ไว้รับ input แสดง output รวมถึง standard error ดังนั้นจะใช้ console พิมพ์คำสั่งอื่นๆ ต่อไม่ได้ ซึ่งจะต่างจากแบบ background ซึ่งเมื่อรัน container แล้วจะแสดง container id ออกมาทางหน้าจอ console และสามารถพิมพ์คำสั่งอื่นได้ ส่วน process จะรันอยู่ใน background จนกว่าจะสั่งให้ container นั้นหยุดทำงาน

ถ้าใช้ -d option หน้า console จะสามารถรับคำสั่งอื่นได้ ต่างจาก default ที่ต้องรอจนกว่า container จะหยุดทำงาน

การใช้งานคำสั่ง docker ps

คำสั่ง docker ps เอาไว้แสดงรายการ container ที่กำลังทำงานอยู่ทั้งหมด

ซึ่งถ้าต้องการให้แสดง container ทั้งหมด รวม container ที่หยุดการทำงานไปแล้วด้วยต้องใช้ -a option docker ps -a

กรณีที่ต้องการสร้าง container และต้องการให้ลบทิ้งเมื่อทำงานเสร็จให้ใช้ --rmoption ตัวอย่าง docker run --rm busybox sleep 1

จะเห็นลอง docker ps -a แล้วไม่มี container id ที่รันคำสั่ง sleep 1 เลย

การกำหนดชื่อให้กับ Container

เนื่องจากการสร้าง container แบบปกติ Docker จะทำการระบุชื่อของ container ให้เองแบบไม่ซ้ำกัน แต่เราสามารถระบุชื่อเองได้โดยใช้ — name optionตัวอย่างdocker run --name hello_world busybox echo "hello worlf"

การดูรายละเอียดภายใน Container

ทำได้โดยใช้คำสั่ง docker inspect id(container/image) เพื่อแสดงข้อมูล low level ของ container หรือ image

การทำ Docker Port Mapping

โดยปกติ ports ที่ถูกเปิดไว้ภายใน container นั้นจะไม่สามารถเข้าใช้งานได้จาก Docker Host ได้ ซึ่งการที่จะเข้าใช้งานได้นั้นต้องทำ publish port ที่ต้องการก่อน ตั้งแต่ขั้นตอนการสร้าง container ขึ้นมา (docker run) ซึ่งสามารถทำได้ 2 วิธี
1. ใช้ -p host_port:container_port เพื่อผูก port ของ container เข้ากับ host
2. ใช้ -P ถ้าต้องการผูกทุก ports ของ container ที่ expose* ไว้ให้กับ host โดยฝั่ง host จะเป็นการ random port
*expose คือ การเปิด port ใน container ใช้ option --expose โดยสามารถระบุเป็น port หรือ เป็นช่วงของ port ก็ได้

ทดลองสร้าง container ของ Tomcat 8.0 ซึ่งมี port เป็น 8080 และต้องการผูกกับ host port ที่ 8888 โดยใช้คำสั่งนี้ docker run -it --rm -p 8888:8080 tomcat:8.0ทดสอบเข้า http://host-ip:8888 จากเบราว์เซอร์

Docker logs

ในกรณีที่รัน container ใน detached mode เราสามารถดู log ของ container ตัวนั้นๆ ได้จาก docker logs ซึ่งมีรูปแบบคำสั่ง คือdocker logs [options] container_id

Docker Images

  • Docker Image Layers
  • สร้าง Docker Image จากคำสั่ง docker commit
  • สร้าง Docker Image ด้วย Dockerfile
  • Dockerfile In-depth
  • วิธีเอา Docker Image ขึ้น Docker Hub

Docker Image Layers

Docker Image แต่ละตัวจริงๆ แล้วมันจะเป็นการอ้างอิงถึงรายการของ read-only layers ซึ่ง layers ที่ว่านี่ก็คือ stack image layer ที่ซ้อนต่อกันจาก base image

จากรูป image ตัวนี้ประกอบด้วย 3 stacked image layers

วิธีการดูว่า Docker Image ที่เราใช้นั้นประกอบด้วย image อะไรบ้าง ดูได้จากคำสั่ง docker history ตัวอย่าง docker history busybox

busyboxจะมี 2 layers คือ base image ที่ add file และ image ที่ 2 สั่งรัน bash

docker history ตัวอย่าง docker history busybox:1.26.2

busybox:1.26.2 จะมี 2 layers คือ base image ที่ add file และ image ที่ 2 สั่งรัน bash

โดยเมื่อสั่งสร้าง container แล้ว มันจะสร้าง Thin R/W layer หรือเรียกว่า container layer ขึ้นมาไว้ข้างบน โดยสามารถมีได้หลายตัวต่อ 1 image ซึ่งการเปลี่ยนทั้งหมดเช่น เขียนไฟล์ใหม่ แก้ไขไฟล์เดิม หรือลบไฟล์ทิ้ง จะเกิดขึ้นที่ container layer ของแต่ละตัว ซึ่งถ้าลบ container ทิ้งไป container layer ก็จะถูกลบไปด้วย โดยไม่ไปแก้ไขอะไรที่ image เลย

การสร้าง Docker Image

มี 2 วิธีในการสร้าง Docker Image
1. commit สิ่งที่เราแก้ไขทั้งหมดใน Docker Container
2. สร้าง Dockerfile

สร้าง Docker Images จากคำสั่ง docker commit

ตัวอย่างถ้าต้องสร้าง image ของ debian ที่มี git client ติดตั้งมาให้พร้อมใช้งาน ทำได้โดย

  • รัน container ของ debian ตัวที่เราจะใช้เป็น base image ก่อน ใช้คำสั่งdocker run -it debian:jessie
  • ทดลองรัน $ git จะพบว่าไม่สามารถทำงานได้ ให้ติดตั้ง git ก่อน $ apt-get update && apt-get install -y git เมื่อติดตั้งเสร็จลองรัน $ git อีกครั้งจะแสดง help ของ git ขึ้นมาแสดงว่าพร้อมใช้งานแล้ว ให้ออกมาจาก container ได้เลย
  • ใช้คำสั่ง Docker commit เพื่อบันทึกการแก้ไขทั้งหมดใน container layers ไปเป็น image ตัวใหม่ ใช้คำสั่งdocker commit container_id repository:tag
จะได้ image ตัวใหม่ ที่มีขนาดใหญ่กว่าเดิม เพราะติดตั้ง git เพิ่มเข้าไป
  • ลองสร้าง container จะ image ใหม่นี่ดู และทดลองใช้คำสั่ง git พบว่ามี git ติดตั้งมาพร้อมใช้งานเลย docker run -it rachata/debian_git:1.0
จะเห็นว่าใช้คำสั่ง git ได้แล้ว

วิธีการเอา Docker Image ขึ้น Docker Hub

  • เริ่มต้นให้สมัครบัญชีผู้ใช้งานก่อนที่ https://hub.docker.com/
ostlab คือ docker_hub_id โดย Repository จะเป็น docker_hub_id/repository name
  • เปลี่ยนชื่อ Repository ของ image ให้ถูกต้อง docker tag source_image[:tag]target_name[:tag] เช่นdocker tag rachata/debian_git:1.0 paretk/debian:1.0
  • ล็อกอินเข้า Docker Hub docker login --username=paretkและใส่ password
  • push image เข้า Docker Hub docker push paretk/debian:1.0
  • เมื่อกลับไปดูที่ https://hub.docker.com/ จะมี repository paretk/debian เพิ่มขึ้นมาแล้ว
จะเห็นว่ามี Paretk/debian อยู่

จะแล้ววววววววววววววว……………………..

--

--