ก่อนอื่นผมขอบอกว่าบทความนี้สามารถทำงานได้เฉพาะบน Linux เท่านั้นครับ (Mac OS ไม่ได้ทดสอบ และ Windows ไม่สามารถรันได้)Docker เป็นชุดซอฟต์แวร์สำหรับทำคอนเทนเนอร์ที่นักพัฒนาทั่วโลกรู้จักกันดี ณ เวลานี้ส่วนใหญ่คงขึ้นระบบโดยใช้ docker กันเกือบหมดแล้ว ด้วยความง่ายและรักษาความเข้ากันได้ของโปรแกรมที่เรารัน
เราสามารถใช้ docker รันโปรแกรมแบบ sandbox กันได้ ซึ่งบทความนี้ผมจะพาผู้อ่านไปเขียนโปรแกรมบนภาษา python สำหรับรันโค้ดภาษาต่าง ๆ แบบ sandbox กับ Docker บน Linux กันแบบง่าย ๆ ครับ
ก่อนอื่นให้ผู้อ่านทำการติดตั้ง docker บน Linux ให้เรียบร้อยก่อน
สามารถอ่านคู่มือการติดตั้ง Docker ได้ที่ docs.docker.com/engine/install/หลังจากนั้น ให้ลง python3 พร้อมกับ pip3 ให้เรียบร้อย
บทความนี้เราจะใช้ไลบรารีที่ชื่อว่า epicbox
epicbox เป็นไลบรารีบนภาษา Python สำหรับรันโค้ดที่ไม่น่าเชื่อถือ มาแยกรันใน docker ซึ่งมันถูกใช้เป็นระบบตรวจคำตอบอัตโนมัติของระบบตรวจสอบคำตอบเขียนโค้ดของเว็บ Stepik.org และใช้ MIT License
เอาล่ะ ต่อไปเรามาลองรันโค้ดง่าย ๆ ใน docker แบบ sandbox กันเลย
เราจะลองโค้ดโปรแกรมภาษา python แบบ sandbox กัน โดยผมจะใช้ python 3.6
ก่อนอื่น ให้ดึง image มาเก็บไว้โดยใช้คำสั่ง
docker pull python:3.6.5-alpine
แล้วใช้คำสั่ง
pip install epicbox
จากนั้น เรามาเขียนโปรแกรมรันโค้ด python ใน docker แบบ sandbox กัน
import epicbox
epicbox.configure(
profiles=[
epicbox.Profile('python', 'python:3.6.5-alpine')
]
)
files = [{'name': 'main.py', 'content': b'print(42)'}]
limits = {'cputime': 1, 'memory': 64}
result = epicbox.run('python', 'python3 main.py', files=files, limits=limits)
print(result)
แล้วรัน ผลลัพธ์
{'exit_code': 0, 'stdout': b'42\n', 'stderr': b'', 'duration': 0.042068, 'timeout': False, 'oom_killed': False}
จะเห็นได้ว่า ผลลัพธ์จะแสดงออกมาเป็น dict การแสดงผลผ่านหน้าจอออกมาอยู่ในคีย์ stdout รวมถึงระยะเวลาการรัน และอื่น ๆ ต่อไป เรามาลองให้รันโค้ดภาษา python โดยมี input อยู่ภายในกัน
import epicbox
epicbox.configure(
profiles=[
epicbox.Profile('python', 'python:3.6.5-alpine')
]
)
files = [{'name': 'main.py', 'content': b'print(input())'}]
limits = {'cputime': 1, 'memory': 64}
result = epicbox.run('python', 'python3 main.py', files=files, limits=limits,stdin="แมว".encode('utf-8'))
print(result)
ผลลัพธ์
{'exit_code': 0, 'stdout': b'\xe0\xb9\x81\xe0\xb8\xa1\xe0\xb8\xa7\n', 'stderr': b'', 'duration': 0.110464, 'timeout': False, 'oom_killed': False}
หรือ
{'exit_code': 0, 'stdout': b'แมว\n', 'stderr': b'', 'duration': 0.110464, 'timeout': False, 'oom_killed': False}
หากเราต้องการรันหลายไฟล์ก็แค่เพิ่มไฟล์เข้าไปใน files ได้ด้วย
import epicbox
epicbox.configure(
profiles=[
epicbox.Profile('python', 'python:3.6.5-alpine')
]
)
files = [
{'name': 'main.py', 'content': b'import cal\nprint(cal.plue(1,2))'},
{'name': 'cal.py', 'content': b'def plue(a,b):\n return a+b'},
]
limits = {'cputime': 1, 'memory': 64}
result = epicbox.run('python', 'python3 main.py', files=files, limits=limits)
print(result)
ผลลัพธ์
{'exit_code': 0, 'stdout': b'3\n', 'stderr': b'', 'duration': 0.036982, 'timeout': False, 'oom_killed': False}
จะเห็นได้ว่าเราสามารถเรียก import ไฟล์อื่นได้ด้วย ซึ่งเราสามารถจำกัด cpu เวลาในการรัน รวมถึงพื้นที่ memory ในการรันโค้ดได้ด้วย
ซึ่งเราสามารถเรียกใช้งาน docker ตามภาษาที่เราต้องการรันได้เลย แถมสามารถรันโค้ดภาษา c โดยสามารถคอมไพล์แล้วรันได้ด้วย เหมาะกับผู้ที่ต้องการรันโค้ดที่ไม่น่าเชื่อถือ และต้องการความปลอดภัย โดยสามารถนำไปใช้สร้างระบบตรวจคำตอบจากการรันโค้ดสำหรับระบบฝึกเขียนโปรแกรมได้ด้วย
อ่านเอกสารเพิ่มเติมได้ที่ https://github.com/StepicOrg/epicbox
0 ความคิดเห็น:
แสดงความคิดเห็น
แสดงความคิดเห็นได้ครับ :)