ในบทความนี้จะเกี่ยวข้องกับการใช้งาน Docker ร่วมกับ Django แบบเบื้องต้น ซึ่งทั้งตัว Django และตัวของ Docker เองแน่นอนว่าเป็นสิ่งที่น่าสนใจทั้งคู่ เมื่อนำทั้งสองอย่างมาใช้งานร่วมกันก็จะช่วยให้ process การทำงานเป็นไปได้อย่างลื่นไหลมากขึ้นเนื่องจากจะทำให้โค้ดที่พัฒนาอยู่เข้าใกล้ความเป็น production มากขึ้นนั่นเอง และบทความนี้เราจะมาเรียนรู้กันเรื่องของการใช้งาน Docker ร่วมกับ Django ใน Development Mode กันก่อน (หมายถึงตอนที่กำลังเขียนโค้ดอยู่) เพื่อความง่าย และจะยังไม่ได้เอาไป deploy กันจริงๆ เอาไว้เดี๋ยวรอบทความถัดๆไปครับ
มารู้จักกันก่อนว่าอะไรเอ่ยคือ Docker ถ้าพูดถึง Docker แล้วหลายๆคนน่าจะนึกถึงภาพของวาฬน่ารักๆตัวนึงซึ่งกำลังขน container กันอยู่ใช่มั้ยครับ สิ่งที่เรามักจะใช้ Docker ทำกันคือการทำสิ่งที่เรียกว่า Container ซึ่งมันคืออะไรกันเนี่ย เดี๋ยวเรามาเล่าถึงประวัติศาสตร์ของโลกของการ deploy สิ่งต่างๆกันก่อน ยุคแรกสุดเลยเวลาเราจะ deploy อะไรก็ตามนี่เราก็จะต้องมีเซิฟเวอร์เป็นของตัวเองก่อนครับ คือต้องซื้อเครื่องมาเลยเครื่องนึง จากนั้นก็ไปทำการ config ต่างๆ setup บลาๆ ซึ่งทำให้มันสามารถเชื่อมต่อกับโลกของอินเตอร์เน็ตได้
Docker (Photo: docker.com)
แน่นอนแหละครับว่าการมีเซิฟเวอร์เป็นของตัวเองก่อน เวลาจะรันอะไรก็ลำบาก แถมยังแพงอีกต่างหาก เราก็เลยมีการแบ่งเซิฟเวอร์ใช้งานกันครับ หมายความว่าเราไม่จำเป็นที่ต้องใช้เซิฟเวอร์ 1 เครื่องรัน services 1 ตัว แต่เราสามารถใช้เซิฟเวอร์เครื่องเดียวกันนี้ รันหลายๆ service พร้อมๆกันไปได้ ประหยัดเงินไปตั้งเยอะ
Server (Photo: canva.com)
แต่ปัญหาก็ยังไม่จบอยู่แค่นั้นครับ เพราะมันอาจจะปัญหาเรื่องของ Dependencies หรือ Library ต่างๆได้ ลองนึกภาพถ้าผมกำลังรัน service ตัวนึง ซึ่งใช้ Python 2 (แอบเก่า;) ) แต่ปรากฎว่ามีเพื่อนที่จะต้องการมาแชร์เครื่องด้วยกันต้องการที่จะใช้งาน Python 3 ที่นี้ก็จะเกิดปัญหาขึ้นมาครับ เพราะเวอร์ชันของ Depencdencies ที่เราต้องการมันไม่ตรงกัน!! ซึ่งแน่นอนว่าเป็นเรื่องที่ปวดหัวมากเพราะฉะนั้นจึงมีการพัฒนาสิ่งหนึ่งขึ้นมาครับ คือสิ่งที่เรียกว่า Virtual Machines (ยังไม่ถึง Docker นะครับ)
มาทำความรู้จัก VM กันสักหน่อยครับ
VM (Photo: howtogeek.com)
Virtual Machine ทำให้เราสามารถจำลองคอมพิวเตอร์ขึ้น บนคอมพิวเตอร์ได้ ที่นี้เวลาเราอยากจะรัน services อะไรเราก็แค่จำลองคอมพิวเตอร์ขึ้นมา แล้วก็ลงแค่ dependencies ที่ต้องการในคอมพิวเตอร์จำลองนั้น ก็จะหมดปัญหาเรื่อง dependencies ตีกันไปได้ครับ แน่นอนว่ามาถึงยุค Virtual Machine แล้วแต่ก็ยังสามารถพัฒนาต่อไปได้ ก็เลยถึงยุคของพระเอกเราในบทความนี้ครับก็คือ Docker นั่นเอง!! (จริงๆแล้วปัจจุบันก็มีสิ่งเจ๋งๆกว่า Docker อยู่เหมือนกันครับ แต่บทความนี้เอา Docker ก่อนแล้วกัน)
ปัญหาของ Virtual Machine คือการจะจำลองคอมพิวเตอร์ขึ้นมา 1 เครื่องเราจะต้องติดตั้งอะไรต่าง ๆ มากมาย ไม่ว่าจะเป็น OS หรือองค์ประกอบต่างๆที่ใช้ในการควบคุมเพื่อจำลองคอมพิวเตอร์ 1 เครื่องขึ้นมา (ใครเคยเล่นพวก VirtualBox จะพอรู้ครับว่ามันกินทรัพยากรสูงมากๆ) สิ่งที่ Docker ทำคือการสร้างสิ่งที่เรียกว่า Container ขึ้นมา โดย Container นึกภาพให้เหมือนกับว่าเป็น environment นึงที่ถูกสร้างขึ้นบนคอมพิวเตอร์ แล้วก็ทำหน้าที่ contain (เป็นกล่อง) สิ่งต่างๆที่เราต้องการใส่ลงไปครับนั่นก็คือการทำงานของ Docker นั่นเอง แต่ถึงแนวคิดของมันจะเรียบง่ายแต่เบื้องหลังการทำงานของมันมีความซับซ้อนพอตัวเลยครับ เช่นว่ามีการใช้งาน Linux อยู่เบื้องหลัง คอยทำหน้าที่จัดสรรทรัพยากรต่างๆ ทำงานกับ Filesystem บลาๆๆ ซึ่งตรงนี้ผมจะขอข้ามไปครับคร่าวๆของ Docker ก็จะประมาณนี้นั่นเอง
วิธีการติดตั้ง Docker ผมจะขออนุญาตข้ามไปนะครับ แต่การติดตั้งไม่ได้ซับซ้อนมากสามารถอ่านได้ที่ Docs ของ Docker โดยตรงได้เลยครับ https://docs.docker.com/get-docker/
แล้วเราจะสร้าง Container ยังไง? การสร้าง Container มีหลายวิธีครับ แต่วิธีที่เป็นที่นิยมที่สุด (เรียกได้ว่า ควรจะทำมากที่สุด) คือการสร้าง Dockerfile ขึ้นมาครับ
โดยสิ่งที่เรียกว่า Dockerfile นี้ก็จะเป็นสิ่งที่ทำหน้าที่บอกองค์ประกอบต่างๆที่เราต้องการให้ container ที่เราต้องการสร้างเป็นครับ แต่เดี๋ยวก่อน ก่อนอื่นที่เราจะเริ่มเขียน Dockerfile กันเรามาไล่เรียงกันดีกว่าว่าการจะสร้างโปรเจค django ขึ้นมาโปรเจคท์หนึ่งนั้นเราต้องทำอะไรกันบ้าง (นับตั้งแต่ 0 เพิ่งได้คอมพิวเตอร์มาเลยครับ 555) โดยสามารถทำได้ตามขั้นตอนดังต่อไปนี้
(env) pip install python
(env) pip install django
(env) django-admin startproject <ชื่อโปรเจคท์>
(env) cd <ชื่อโปรเจคท์>
(env) python manage.py runserver
หน้า default ของ django
แชว้บ~ ได้จรวดพร้อมโปรเจคท์ Django มาโปรเจคท์หนึ่ง เดี๋ยวเรามาต่อกันที่ Docker กันดีกว่าข้างบนเป็นขั้นตอนเมื่ออยากที่จะสร้างโปรเจคท์ใหม่ขึ้นมาใช่มั้ยครับ แต่ถ้าหากเราจะใช้งาน Docker เราจะต้องทำเหมือนกับว่า เราต้องการจะเอาโปรเจคท์ของเรา ไปรันในเครื่องอื่นเราจะทำยังไงกันก็อย่างแรกเลยคือเราต้องมีรายชื่อของ library python ที่เราจะใช้กันก่อนครับ ก็ใช้คำสั่ง
$ pip freeze > requirements.txt
เพื่อนำ library ต่างๆของเรามาก่อน
asgiref==3.3.1
Django==3.1.4
pytz==2020.5
sqlparse==0.4.1
เดี๋ยวเรามาไล่ขั้นตอนกันใหม่ดีกว่าว่าถ้าเรายก Django ของเราไปเครื่องเพื่อนเราจะทำยังไง เริ่มกันตั้งแต่ 0 ได้คอมมาใหม่ๆเหมือนเดิมครับ โดยมีขั้นตอนดังนี้
เมื่อได้ขั้นตอนนี้มาแล้วเดี๋ยวมาสร้างไฟล์ Dockerfile กันเลยครับ สร้างไฟล์ใหม่ชื่อ Dockerfile มาก่อน จากนั้นพิมพ์ลงไปตามนี้ครับ
Dockerfile
FROM python:3
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"]
โดยสิ่งที่เราเขียนไปใน Dockerfile ก็จะเป็นไปตามขั้นตอนที่เราไล่ไปในข้างบนเด๊ะๆเลย (มีแปลกๆตรง EXPOSE เดี๋ยวไว้อธิบายข้างล่างอีกทีครับ)
ก่อนอื่นเราจะต้องทำการ build ไฟล์ Dockerfile ของเราก่อนครับ ซึ่งการ Build เมื่อเสร็จสิ้นเราจะได้สิ่งที่เรียกว่า Image ออกมา เมื่อได้ Image เราจึงจะสามารถนำไปสร้าง Container ได้ครับ Build ด้วยคำสั่ง docker build -t <ชื่อ image ที่ต้องการตั้งfile
ตัวอย่างเช่น
$ pip freeze > requirements.txt
ตอนรันระวังอย่าลืม(Dot) . ด้วยนะครับ
เมื่อได้ image มาแล้วให้ใช้คำสั่งรันด้วยการรันตามนี้ครับ
$ docker run -p 8000:8000 -v $(pwd):/app <ชื่อ image ที่พึ่งตั้งไป>
Note: Windows: ไม่มีคำสั่ง pwd ใช้เป็น %cd% แทนครับ
เดี๋ยวไว้มาอธิบายกันดีกว่าว่าคำสั่งนี้มันทำอะไรได้บ้างครับ คำสั่งพื้นฐานสุดๆเลยคือ docker run <ชื่อ image> แค่เพียงเท่านี้เราก็สามารถที่จะรัน Container ได้แล้ว แต่เราเพิ่มแท็ก -p และ -v ขึ้นมาเนื่องจากว่าจำเป็นต้องมีการ config ให้เจ้า container สามารถสื่อสารกับเราได้ครับ
-p ใช้สำหรับการ map port โดยปกติแล้วเมื่อสร้าง container ขึ้นมาตัว docker จะไม่ได้มีการเชื่อมพอร์ตให้เราโดยอัตโนมัติ เราจำเป็นที่จะต้องเชื่อมเองครับ -p 8000:8000 หมายถึงเชื่อมต่อพอร์ต 8000 ของเครื่องเราเข้ากับ 8000 ของตัว container (EXPOSE ใน Dockerfile ก็มีไว้เพื่อเหตุผลเดียวกันครับ)
-v คล้ายๆกันกับการ map port แต่ว่าเรา map พื้นที่ใน harddisk ของเราแทนครับ -v $(pwd):/app ของผมคือการ map directory ปัจจุบันของผมเข้ากับ /app ในตัว container นั่นเอง pwd ใน Unix เป็นคำสั่งเพื่อแสดงที่อยู่ไดเรคทอรี่ปัจจุบันของเรา
เมื่อรันคำสั่งแล้วลองเปิด localhost:8000 ดูก็จะเห็น
รันได้เหมือนกันกับเครื่องต้นทาง
แสดงว่าการใช้งาน Docker ร่วมกับ Django ของเราเสร็จสมบูรณ์ครับ ตอนนี้ก็ถ้าใครอยากลองแก้ไขไฟล์ดูแล้วดูว่าหน้าเว็บของเราเปลี่ยนไปด้วยหรือไม่ก็สามารถลองทำได้ตามสะดวกเลยครับ สำหรับบทความนี้ก็ขอขอบคุณมากครับ เจอกันใหม่บทความหน้าครับ
กิจกรรมที่กำลังจะมาถึง
ไม่พลาดกิจกรรมเด็ด ๆ ที่น่าสนใจ
Event นี้จะเริ่มขึ้นใน April 25, 2023
รายละเอียดเพิ่มเติม/สมัครเข้าร่วมคอร์สเรียนไพธอนออนไลน์ที่เราได้รวบรวมและได้ย่อยจากประสบการณ์จริงและเพื่อย่นระยะเวลาในการเรียนรู้ ลองผิด ลองถูกด้วยตัวเองมาให้แล้ว เพราะเวลามีค่าเป็นอย่างยิ่ง พร้อมด้วยการซัพพอร์ตอย่างดี