สร้าง Docker Container ใช้สำหรับการ Deploy ML Model
Contained everything in Docker!
จากตอนก่อนหน้านี้ ได้มีการ Deploy ML Model ด้วย Git และ Heroku กันไปแล้ว ตอนนี้อยากลดขั้นตอนการทำงานของ Git ลง เพราะไม่อยากเชื่อมต่อหลาย Connection ทั้ง Git และ Heroku
ดังนั้นการใช้งาน Docker จึงเป็นทางออกที่ดี เพราะสุดท้ายแล้วสามารถ Deploy docker container ขึ้นไปที่ Heroku ได้เลยตรง ๆ โดยที่ไม่ต้องผ่าน Git ไฟล์สำหรับ Blog ตอนนี้ใช้เป็นของ Project ในตอนก่อนหน้านี้ทั้งหมด ดังนั้นสามารถดูรายละเอียดได้จาก Link ด้านล่าง
Docker
Docker คืออะไร… ก่อนอื่นควรเริ่มทำความรู้จักกับ Docker ที่เป็นที่นิยมมาก สำหรับการทำงานสาย Tech ซึ่งสามารถนำปรับใช้ให้เข้างานสาย Data หรือ Risk model ได้เช่นกัน
ปัญหาที่เกิดขึ้นบ่อยครั้งสำหรับการทำงานเกี่ยวกับ Data ด้วยระบบเปิด (SAS ถึงว่าเป็นระบบปิด อาจเจอปัญหาลักษณะนี้น้อยกว่า) ในที่นี้อาจหมายถึง Python หรือ R ที่จำเป็นต้องพึ่งพาเครื่องมือจากหลาย Sources บ่อยครั้งที่การทำงานของโปรแกรมผิดพลาด เนื่องจากเวอร์ชั่นที่ไม่ตรงกัน
Docker สามารถเข้าช่วยแก้ไขปัญหานี้ได้ เพราะ Docker มีการทำงานคล้ายกับ Virtual Machine ที่เป็นเหมือนการจำลองสภาพแวดล้อมในการทำงาน ไม่ว่าจะเป็น OS หรือ Environment ต่าง ๆ จากเดิมที่เคยส่งเป็น Script ให้กับทาง User ต่อไปสามารถส่งเป็น Docker image หรือ Container เพื่อช่วยให้การทำงาน Smooth มากขึ้น
Dockerfile
Dockerfile เป็นเหมือนชุดคำสั่ง ในการสั่งให้ Build image ด้วยองค์ประกอบตามที่กำหนด เช่น ใช้งานบน Service อะไร ต้องติดตั้งอะไรบ้าง เพื่อการใช้งาน Dockerfile มีความคล้ายกับ Procfile เคยใช้งานจากตอนก่อนหน้านี้
Docker image
Docker image เป็นต้นแบบก่อนเริ่มสร้าง Docker container มีการตั้งค่าหรือจำลองทุกอย่างไว้ตามที่ระบุจาก Dockerfile
Docker container
Docker container เป็น Application สุดท้ายที่เป็น Service ที่ต้องการใช้งานจริง ๆ สามารถนำ Container เพื่อไปใช้งานใน CPU, RAM หรือใน Network ต่าง ๆ ได้
Build docker
Code และไฟล์ สำหรับ Project ทั้งหมด สามารถใช้ได้จากตอนก่อนหน้านี้ มีส่วนที่ต้องแก้ไขใน Python script เนื่องจากต้องปรับให้ทำงานร่วมกับ Docker container ได้
ในไฟล์ app.py
มีการอัพเดตเพิ่มที่
- Line ที่ 3 Import
os
เข้ามาเป็นจัดการกับ Path - Line ที่ 27 กำหนด Post ให้เป็น 5000
- Line ที่ 28 กำหนด Host และ Post ให้กับ Flask application เนื่องจาก Docker container ไม่สามารถชี้ไปที่ Default host ที่ 127.0.0.1 ได้ ดังนั้นจึงจำเป็นต้องใช้งานผ่าน Localhost แทน ส่วน Default post ที่มีค่า Default เป็น 5000 อยู่แล้ว แต่การระบุ Port ลักษณะนี้ช่วยไม่ให้เกิด App crash ในขั้นตอนการ Deployment ได้
ก่อนเริ่ม Build docker image และ docker container ต้องทำการติดตั้ง Docker ที่เครื่องก่อน สามารถ Download และติดตั้งได้จาก Link ด้านล่าง
เมื่อติดตั้งแล้ว ให้ลองเรียก Docker ขึ้นมาจาก Command prompt เช่น
docker --version
ถ้าไม่มี Error แล้วสามารถแสดงเวอร์ชั่นได้ แสดงว่าติดตั้งได้สมบูรณ์
ต่อมาให้สร้าง Dockerfile โดย Create emtpy file ที่ไม่ต้องระบุนามสกุลขึ้นมาจาก Editor อะไรก็ได้ จากนั้นให้ระบุ Requirments สำหรับ Docker image ตามด้านล่าง
FROM python:3.7.9-slim-busterWORKDIR /appCOPY requirements.txt .RUN pip install -r requirements.txtCOPY . .EXPOSE 5000CMD ["python", "app.py"]
ดังนั้น Project structure ประกอบไปด้วย Folder และไฟล์ตามผังด้านล่าง
templates
---index.html
app.py
model.pk
Dockerfile
requirements.txt
เริ่มอธิบาย Line by line เริ่มจาก FROM
คือการระบุ Base image ว่าให้ Container เรียกใช้งาน Base ประเภทไหน ซึ่ง Application ถูกเขียนด้วย Python ดังนั้น Base image จึงต้องเป็น Python แต่ Python มีให้ใช้งานหลายเวอร์ชั่น และหลายขนาดนั้น ดังนั้นสามารถเลือกให้เหมาะสมกับ Application ได้จาก Link ด้านล่าง
WORKDIR
เป็น Directory ที่จะถูกสร้างภายใน Docker image ในที่นี้ขอตั้งชื่อว่า app
COPY
เป็นการ Copy dependencies file ซึ่งคือ Requirements.txt
ที่ภายในระบุ Python libraries ที่จำเป็นต่อการรัน Application
RUN
เป็นการสั่งให้รัน Dependencies file เพื่อติดตั้ง Libraries ใน Docker image
COPY . .
เป็นการบอกให้ Copy ไฟล์ที่เหลือทั้งหมดใน Project ลงใน Docker image
EXPOSE 5000
เป็นการกำหนด Port ให้ Container สำหรับการเรียกใช้งานภายนอก Network เช่นการ Push ไปที่ Heroku เป็นต้น
CMD ["python", "app.py"]
เป็น Command line ในการบอกให้ Container เริ่มทำงาน ซึ่งเหมือนเป็นการสั่งรัน Python script บน Localhost
เมื่อทุกอย่างพร้อมแล้ว สามารถเริ่ม Build docker image โดยใช้คำสั่งตามด้านล่าง
docker image build -t image-name .
ต้องใส่ .
หลังจากชื่อ Docker image ด้วย ไม่งั้นจะไม่สามารถรัน Build ได้ เมื่อได้ Log return เหมือนด้านล่างแสดงว่าการสร้าง Docker image เสร็จสมบูรณ์
[+] Building 58.8s (10/10) FINISHED
=> [internal] load build definition from Dockerfile 0.1s
=> [2/5] WORKDIR /app 5.1s
=> [3/5] COPY requirements.txt . 0.2s
=> [4/5] RUN pip install -r requirements.txt 25.7s
=> [5/5] COPY . . 0.1s
=> exporting to image 2.4s
=> => exporting layers 2.4s
=> => writing image sha256:9b7c7ec953f3e0c421c228d07fdbb9b3ed76fdb8f37331ab8303d 0.0s
=> => naming to docker.io/library/ml-model 0.0s
สามารถตรวจสอบ Docker image ที่เพิ่ง Build ได้ด้วยคำสั่ง docker image ls เป็นการแสดง List ของ Docker image ที่ทั้งหมดในเครื่อง
REPOSITORY TAG IMAGE ID CREATED SIZE
ml-model latest 9b7c7ec953f3 2 minutes ago 352MB
ต่อมาสามารถทดลองรัน Container ได้ด้วยการระบุ Port ที่เขียนไว้ใน app.py ด้วยคำสั่ง
docker run -p 5000:5000 -d image-name
เมื่อรันคำสั่งด้านบน Terminal จะ Return ค่า Container ID กลับมาให้เก็บค่านั้นไว้ เพราะต้องใช้ในการหยุดรัน Container เมื่อ Container ทำงานแล้ว สามารถทดสอบการทำงานของ Container ได้ด้วยการเข้า localhost:5000
ผ่าน Web Browser ถ้าสามารถเข้าใช้งานได้เหมือนรูปด้านล่าง แสดงว่าการ Build image และ Run container เสร็จสมบูรณ์
สามารถหยุดรัน Container ได้ด้วยคำสั่งด้านล่าง
docker container stop container-id
นอกจาก Stop container แล้วอาจต้องมีการหยุดรัน Service อื่น ๆ ที่ติดอยู่เบื้องหลังด้วย สามารถใช้คำสั่ง docker system prune
เมื่อทุกอย่างที่ Local พร้อมแล้ว สามารถนำ Docker image ไป Deploy ต่อได้
Deployment with Heroku
ตอนก่อนหน้านี้ มีการ Create application บนหน้าเว็บ Heroku ตอนนี้เลยขอทำทั้งหมดบน Command line เพื่อความแตกต่างบ้าง ก่อนอื่นให้ Loing เข้าไปที่ Heroku โดยใช้คำสั่ง
heroku container:login
เมื่อได้ Return กลับมาว่า Login Succeeded
สามารถทำการ Create application ได้ด้วยคำสั่ง
heroku create app-name
โดยที่ app-name
ให้ตั้งชื่อที่ไม่ซ้ำกับ Domain อื่น ๆ อาจต้องมีการเลือกใช้หลายชื่อหน่อย ซึ่งตอนนี้ขอใช้ชื่อว่า testingdockermlmodel
ถ้าได้ Return เหมือนด้านล่างแสดงว่าสามารถใช้ชื่อ Application นั้น ๆ ได้
Creating testingdockermlmodel... done
https://testingdockermlmodel.herokuapp.com/ | https://git.heroku.com/testingdockermlmodel.git
ต่อมาเป็นการ Push container ขึ้นไปที่ Heroku ให้ใช้ Command ด้านล่าง
heroku container:push web --app app-name
ได้ถ้า Return กลับมาเป็น
Your image has been successfully pushed. You can now release it with the 'container:release' command.
สามารถทำการ Release ด้วย Command ด้านล่าง เป็นขั้นตอนสุดท้ายสำหรับการ Deployment docker container บน Heroku
heroku container:release web --app app-name
Conclusion
จบไปอีกหนึ่งรูปแบบในการ Deployment ML Model ด้วย Docker และ Heroku การทำ Docker image ช่วยลดขั้นตอนการใช้ GitHub และสามารถ Push ไปที่ Heroku ได้ทันที แต่อาจมีความยุ่งยากตอน Build docker image อยู่บ้าง
ผลจากที่ทำมาทั้งหมดในตอนนี้ สามารถเข้าไปดูได้ที่ https://testingdockermlmodel.herokuapp.com/
อัพเดต
Model materials ทั้งหมดของ Blog ตอนนี้ สามารถดูได้ที่ GitHub ด้านบน