<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pargorn Ruasijan</title>
    <description>The latest articles on DEV Community by Pargorn Ruasijan (@xnewz).</description>
    <link>https://dev.to/xnewz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F768722%2F0ac28ebc-df90-4569-91a0-bb56f2ed7992.png</url>
      <title>DEV Community: Pargorn Ruasijan</title>
      <link>https://dev.to/xnewz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xnewz"/>
    <language>en</language>
    <item>
      <title>วิธีใช้ OWASP ZAP ทดสอบความปลอดภัยของเว็บแอปพลิเคชัน โดยใช้ OWASP Juice Shop</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Fri, 13 Jun 2025 14:34:00 +0000</pubDate>
      <link>https://dev.to/xnewz/withiiaich-owasp-zap-thdsbkhwaampldphaykhngewbaepphliekhchan-odyaich-owasp-juice-shop-1ee0</link>
      <guid>https://dev.to/xnewz/withiiaich-owasp-zap-thdsbkhwaampldphaykhngewbaepphliekhchan-odyaich-owasp-juice-shop-1ee0</guid>
      <description>&lt;p&gt;การทดสอบช่องโหว่ของเว็บแอปพลิเคชันเป็นสิ่งที่จำเป็นสำหรับนักพัฒนาและผู้ดูแลระบบ OWASP ZAP เป็นหนึ่งในเครื่องมือยอดนิยมที่ช่วยให้เราสามารถตรวจสอบความปลอดภัยของเว็บแอปได้อย่างมีประสิทธิภาพ&lt;/p&gt;

&lt;p&gt;ในบทความนี้ เราจะพาไปรู้จักกับ OWASP ZAP และวิธีใช้งานร่วมกับ Juice Shop เพื่อค้นหาและวิเคราะห์ช่องโหว่ของเว็บแอป&lt;/p&gt;

&lt;h2&gt;
  
  
  OWASP ZAP คืออะไร
&lt;/h2&gt;

&lt;p&gt;OWASP ZAP (Zed Attack Proxy) เป็นเครื่องมือ Open Source ที่ช่วยทดสอบความปลอดภัยของเว็บแอปพลิเคชันโดยการสแกนหาช่องโหว่ เช่น SQL Injection, Cross-Site Scripting (XSS), Security Misconfiguration และอื่น ๆ&lt;/p&gt;

&lt;p&gt;ZAP มีฟีเจอร์ที่หลากหลาย เช่น การสแกนอัตโนมัติ การตรวจสอบความปลอดภัยแบบ Manual การสร้างรายงาน และการสนับสนุนการทำงานร่วมกับเครื่องมืออื่น ๆ ZAP เป็นเครื่องมือที่เหมาะสำหรับนักพัฒนาซอฟต์แวร์ นักทดสอบความปลอดภัย และผู้ที่สนใจในด้าน Cybersecurity&lt;/p&gt;

&lt;h2&gt;
  
  
  OWASP Juice Shop คืออะไร
&lt;/h2&gt;

&lt;p&gt;OWASP Juice Shop เป็นเว็บแอปพลิเคชันที่สร้างขึ้นเพื่อใช้เป็นตัวอย่างในการทดสอบช่องโหว่ด้านความปลอดภัย มันเต็มไปด้วยช่องโหว่ยอดนิยมตาม OWASP Top 10 ซึ่งเหมาะสำหรับใช้เรียนรู้และฝึกฝนการทดสอบด้าน Security&lt;br&gt;
Juice Shop มีฟีเจอร์ที่หลากหลาย เช่น การจัดการบัญชีผู้ใช้ การชำระเงินออนไลน์ และการจัดการสินค้า ซึ่งทำให้มันเป็นตัวอย่างที่ดีในการทดสอบความปลอดภัยของเว็บแอปพลิเคชัน&lt;/p&gt;
&lt;h2&gt;
  
  
  ติดตั้งและรัน OWASP Juice Shop บน Local
&lt;/h2&gt;

&lt;p&gt;&lt;br&gt;
Juice Shop รองรับหลายวิธีในการรัน เช่น Docker, Node.js, Heroku, และ AWS&lt;br&gt;
ในที่นี้เราจะใช้ Docker เพื่อรัน Juice Shop บน Local&lt;br&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  แต่วันนี้เราจะใช้ Docker ในการติดตั้ง Juice Shop เพราะมันง่ายและรวดเร็ว
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ติดตั้ง Docker บนเครื่อง &lt;a href="https://www.docker.com/get-started" rel="noopener noreferrer"&gt;ดาวน์โหลดที่นี่&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;เปิด Terminal และรันคำสั่ง
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8888:3000 bkimminich/juice-shop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;รอจนกระทั่ง Juice Shop รันเสร็จ จากนั้นเปิดเว็บเบราว์เซอร์และไปที่ &lt;a href="http://localhost:8888" rel="noopener noreferrer"&gt;http://localhost:8888&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydc5q1tji6ttx02330tm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fydc5q1tji6ttx02330tm.png" alt="Image description" width="800" height="622"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ติดตั้งและตั้งค่า OWASP ZAP
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ติดตั้ง OWASP ZAP
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ดาวน์โหลด OWASP ZAP จาก &lt;a href="https://www.zaproxy.org/download/" rel="noopener noreferrer"&gt;เว็บไซต์ทางการ&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ติดตั้งตามขั้นตอนของระบบปฏิบัติการที่คุณใช้งาน&lt;/li&gt;
&lt;li&gt;เปิด OWASP ZAP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60d5ro6m9iao8hfeskeu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F60d5ro6m9iao8hfeskeu.png" alt="Image description" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ตั้งค่า Proxy ใน OWASP ZAP
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เปิด ZAP แล้วไปที่ &lt;code&gt;Tools&lt;/code&gt; → &lt;code&gt;Options&lt;/code&gt; → &lt;code&gt;Network&lt;/code&gt; → &lt;code&gt;Local Server/Proxies&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;ตั้งค่า &lt;code&gt;Address&lt;/code&gt; เป็น &lt;code&gt;localhost&lt;/code&gt; และ &lt;code&gt;Port&lt;/code&gt; เป็น &lt;code&gt;8080&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;กด &lt;code&gt;OK&lt;/code&gt; เพื่อบันทึกการตั้งค่า&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8sn4kjvpigql0ds9om4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8sn4kjvpigql0ds9om4.png" alt="Image description" width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
การตั้งค่า Proxy จะช่วยให้ ZAP สามารถดักจับและวิเคราะห์การเชื่อมต่อระหว่างเว็บเบราว์เซอร์และ Juice Shop ได้ เรียกง่าย ๆ ว่า ทุก Request ที่ส่งจากเบราว์เซอร์จะถูกส่งไปยัง ZAP&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  ใช้ OWASP ZAP สแกน OWASP Juice Shop
&lt;/h2&gt;

&lt;h3&gt;
  
  
  สแกนอัตโนมัติ (Automated Scan)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เปิด OWASP ZAP → ไปที่แท็บ &lt;code&gt;Quick Start&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;เลือก &lt;code&gt;Automated Scan&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwez8robgmi9zgt7rb3pv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwez8robgmi9zgt7rb3pv.png" alt="Image description" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ใส่ URL ของ Juice Shop (&lt;a href="http://localhost:8888" rel="noopener noreferrer"&gt;http://localhost:8888&lt;/a&gt;) ในช่อง &lt;code&gt;URL to attack&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;กด &lt;code&gt;Attack&lt;/code&gt; เพื่อเริ่มการสแกน&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngvbfw43trztob8f8u00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fngvbfw43trztob8f8u00.png" alt="Image description" width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;รอจนกระทั่งการสแกนเสร็จสิ้น&lt;/li&gt;
&lt;li&gt;เมื่อการสแกนเสร็จสิ้น คุณจะเห็นรายงานช่องโหว่ที่พบในแท็บ &lt;code&gt;Alerts&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;วิเคราะห์และแก้ไขปัญหาที่พบ&lt;/li&gt;
&lt;li&gt;ไปที่แท็บ &lt;code&gt;Alerts&lt;/code&gt; คุณจะเห็นรายการช่องโหว่ เช่น&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ตารางแสดงตัวอย่างการสแกนช่องโหว่
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ระดับความเสี่ยง&lt;/th&gt;
&lt;th&gt;ประเภทช่องโหว่&lt;/th&gt;
&lt;th&gt;วิธีแก้ไข&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;🔴 High&lt;/td&gt;
&lt;td&gt;SQL Injection&lt;/td&gt;
&lt;td&gt;ใช้คำสั่ง SQL ที่ปลอดภัย (Prepared Statements) หรือใช้ ORM เพื่อลดความเสี่ยง&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟡 Medium&lt;/td&gt;
&lt;td&gt;Content Security Policy (CSP) Header Not Set&lt;/td&gt;
&lt;td&gt;เพิ่ม CSP Header เพื่อป้องกันการโจมตีแบบ XSS และการโหลดเนื้อหาจากแหล่งที่ไม่ปลอดภัย&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;🟢 Low&lt;/td&gt;
&lt;td&gt;X-Content-Type-Options Header Missing&lt;/td&gt;
&lt;td&gt;ตั้งค่า X-Content-Type-Options: nosniff ใน Header เพื่อป้องกันการแอบเปลี่ยนประเภทไฟล์&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp74rmz17l3sxtg33exv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgp74rmz17l3sxtg33exv.png" alt="Image description" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;คลิกที่ช่องโหว่เพื่อดูรายละเอียดเพิ่มเติม เช่น คำอธิบาย วิธีการโจมตี และวิธีการแก้ไข&lt;/li&gt;
&lt;li&gt;คุณสามารถคลิกที่ &lt;code&gt;Request&lt;/code&gt; และ &lt;code&gt;Response&lt;/code&gt; เพื่อดูรายละเอียดของ Request และ Response ที่ถูกส่งไปยัง Juice Shop&lt;/li&gt;
&lt;li&gt;คุณสามารถใช้ข้อมูลเหล่านี้ในการวิเคราะห์และปรับปรุงความปลอดภัยของเว็บแอปพลิเคชัน&lt;/li&gt;
&lt;li&gt;นอกจากนี้ ZAP ยังมีฟีเจอร์การสร้างรายงานที่ช่วยให้คุณสามารถบันทึกผลการสแกนได้&lt;/li&gt;
&lt;li&gt;ไปที่ &lt;code&gt;Report&lt;/code&gt; → &lt;code&gt;Generate Report&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;เลือกรูปแบบรายงานที่ต้องการ เช่น HTML, XML, Markdown&lt;/li&gt;
&lt;li&gt;กด &lt;code&gt;Generate&lt;/code&gt; เพื่อสร้างรายงาน&lt;/li&gt;
&lt;li&gt;รายงานจะถูกบันทึกในโฟลเดอร์ที่คุณเลือก&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1g5petypj1y055w4of36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1g5petypj1y055w4of36.png" alt="Image description" width="800" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>การ Deploy Flask API ด้วย Kubernetes</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Fri, 13 Jun 2025 14:29:44 +0000</pubDate>
      <link>https://dev.to/xnewz/kaar-deploy-flask-api-dwy-kubernetes-h6m</link>
      <guid>https://dev.to/xnewz/kaar-deploy-flask-api-dwy-kubernetes-h6m</guid>
      <description>&lt;p&gt;Kubernetes เป็นเครื่องมือสำหรับการจัดการแอปพลิเคชันที่ใช้ container อย่าง Docker ซึ่งช่วยให้เราสามารถ deploy และ scale แอปพลิเคชันได้ง่าย&lt;br&gt;
ในบทความนี้เราจะมา deploy Flask API ด้วย Kubernetes โดยจะแสดงขั้นตอนตั้งแต่การเตรียมแอปพลิเคชันไปจนถึงการ deploy ลงใน Kubernetes cluster&lt;/p&gt;
&lt;h2&gt;
  
  
  ขั้นตอนที่ 1 เตรียม Flask API
&lt;/h2&gt;

&lt;p&gt;เริ่มต้นด้วยการสร้าง Flask API ง่าย ๆ สำหรับการทดสอบ&lt;/p&gt;
&lt;h3&gt;
  
  
  1. สร้างโฟลเดอร์ใหม่สำหรับโปรเจค Flask
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;flask-api
&lt;span class="nb"&gt;cd &lt;/span&gt;flask-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. สร้างไฟล์ app.py สำหรับ Flask API
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello_world&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello, Kubernetes!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  3. สร้างไฟล์ requirements.txt
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flask==3.1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  ขั้นตอนที่ 2 สร้าง Docker Image สำหรับ Flask API
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. สร้างไฟล์ Dockerfile ในโฟลเดอร์โปรเจค
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# ใช้ base image จาก Python&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.9-slim&lt;/span&gt;

&lt;span class="c"&gt;# กำหนด directory ภายใน container&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# คัดลอกไฟล์ requirements.txt และติดตั้ง dependencies&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt /app/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# คัดลอกโค้ดไปยัง /app/ ใน container&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /app/&lt;/span&gt;

&lt;span class="c"&gt;# เปิด port ที่จะใช้งาน&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 5000&lt;/span&gt;

&lt;span class="c"&gt;# รัน Flask API&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. สร้าง Docker image
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; flask-api &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  3. ทดสอบการทำงานของ Flask API ใน Docker
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 5000:5000 flask-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;เปิด browser และไปที่ &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt; จะเห็นข้อความ “Hello, Kubernetes!”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  ขั้นตอนที่ 3 เตรียม Kubernetes
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;สร้างไฟล์สำหรับการ deploy แอปพลิเคชันใน Kubernetes&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  1. สร้างไฟล์ flask-api-deployment.yaml สำหรับ Deployment และ Service
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask-api&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;  &lt;span class="c1"&gt;# จำนวน replicas หรือ pod ที่ต้องการ&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask-api&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask-api&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask-api&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;username&amp;gt;/flask-api:latest&lt;/span&gt;  &lt;span class="c1"&gt;# Docker image ที่เราสร้างขึ้น&lt;/span&gt;
        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask-api-service&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;flask-api&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt; &lt;span class="c1"&gt;# Port ของ container&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LoadBalancer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deployment&lt;/strong&gt; กำหนดจำนวน replicas ของ pod (ที่นี่ตั้งไว้ 3 replicas) และ image ที่จะใช้ในการ deploy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service&lt;/strong&gt; กำหนด service ที่เชื่อมต่อกับ pod ซึ่งจะเปิด port 80 และเชื่อมต่อกับ port 5000 ของ container&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  ขั้นตอนที่ 4 Deploy Flask API ไปยัง Kubernetes
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. อัปโหลด Docker image ไปยัง Docker registry (เช่น Docker Hub หรือ GCR)
&lt;/h3&gt;

&lt;p&gt;&lt;br&gt;
&lt;code&gt;GCR&lt;/code&gt; คือ Google Container Registry ที่ใช้เก็บ Docker image บน Google Cloud Platform แบบ Private Registry&lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag flask-api:latest &amp;lt;username&amp;gt;/flask-api:latest
docker push &amp;lt;username&amp;gt;/flask-api:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. ใช้ kubectl เพื่อ deploy แอปพลิเคชันไปยัง Kubernetes cluster
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; flask-api-deployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. ตรวจสอบการทำงานของ Deployment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get deployments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbieb9iexgodwnebnd1qs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbieb9iexgodwnebnd1qs.png" alt="Image description" width="800" height="158"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ถ้าคุณเห็น replicas ที่ต้องการและ replicas ที่กำลังทำงาน แสดงว่า Deployment ทำงานถูกต้อง (อย่างน้อยต้องมี Ready 1 จาก 3) แต่ควรมี Ready 3 จาก 3 ถ้าไม่มีปัญหาใด ๆ&lt;/p&gt;
&lt;h3&gt;
  
  
  4. ตรวจสอบ Pod
&lt;/h3&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2je1433n1bqmvmpossx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2je1433n1bqmvmpossx.png" alt="Image description" width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ถ้า Pod ทั้งหมดมีสถานะ &lt;code&gt;Running&lt;/code&gt; แสดงว่า Pod ทำงานถูกต้อง&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5. ตรวจสอบ Service
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqaz2n9zynw0vzwqzq3l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqaz2n9zynw0vzwqzq3l.png" alt="Image description" width="800" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ถ้าใช้ LoadBalancer service ต้องใช้ &lt;code&gt;EXTERNAL-IP&lt;/code&gt; เพื่อเข้าถึง Flask API ในที่นี้คือ &lt;code&gt;localhost&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ขั้นตอนที่ 5 ทดสอบการทำงานของ Flask API บน Kubernetes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;หากคุณใช้ LoadBalancer service เปิด browser และไปที่ IP ที่ได้จาก kubectl get services และ port 80&lt;/li&gt;
&lt;li&gt;คุณควรเห็นข้อความ &lt;code&gt;“Hello, Kubernetes!”&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjt9v7uqn6vn94qsyttr9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjt9v7uqn6vn94qsyttr9.png" alt="Image description" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ขั้นตอนที่ 6 การอัปเดต
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. หากต้องการอัปเดตแอปพลิเคชัน เพียงแค่สร้าง Docker image ใหม่และอัปโหลดไปยัง Docker registry
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; flask-api:latest &lt;span class="nb"&gt;.&lt;/span&gt;
docker tag flask-api:latest &amp;lt;username&amp;gt;/flask-api:latest
docker push &amp;lt;username&amp;gt;/flask-api:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. ทำการ update deployment บน Kubernetes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;set &lt;/span&gt;image deployment/flask-api flask-api&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;username&amp;gt;/flask-api:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. ตรวจสอบการอัปเดต
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  สรุป
&lt;/h2&gt;

&lt;p&gt;การ deploy Flask API ด้วย Kubernetes เป็นวิธีที่ดีในการจัดการแอปพลิเคชันที่สามารถ scale ได้&lt;br&gt;
ถ้าต้องการความสะดวกในการจัดการ Kubernetes cluster การใช้ Rancher จะทำให้คุณสามารถ deploy ได้เร็วขึ้นและง่ายมากขึ้น Rancher มี UI ที่ใช้งานง่ายและช่วยให้คุณสามารถจัดการ Kubernetes cluster ได้ง่ายขึ้น&lt;/p&gt;

&lt;p&gt;ถ้ากำลังมองหาวิธีการ deploy Flask API ที่สะดวกและรวดเร็ว การใช้ Rancher ร่วมกับ Kubernetes น่าจะเป็นทางเลือกที่ดีครับผมมม ลองดูกันนะครับผมมม&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>flask</category>
      <category>devops</category>
      <category>api</category>
    </item>
    <item>
      <title>Python Web Framework ความแตกต่างระหว่าง Flask และ Django</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Fri, 13 Jun 2025 14:23:00 +0000</pubDate>
      <link>https://dev.to/xnewz/python-web-framework-khwaamaetktaangrahwaang-flask-aela-django-579h</link>
      <guid>https://dev.to/xnewz/python-web-framework-khwaamaetktaangrahwaang-flask-aela-django-579h</guid>
      <description>&lt;p&gt;ถ้าคุณอยากใช้ Python ที่อยากสร้างเว็บแอปพลิเคชันสักตัว แต่ยังไม่แน่ใจว่าจะเลือกใช้ Flask หรือ Django ดี ลองมาดูข้อแตกต่างระหว่างสองตัวนี้กันดีกว่า! ทั้งสองเป็น Framework ที่ยอดนิยมในวงการ Python แต่ก็มีลักษณะการใช้งานที่ต่างกัน ถ้าพร้อมแล้วก็มาเริ่มกันเลย!&lt;/p&gt;

&lt;h2&gt;
  
  
  Flask – ตัวเล็กๆ แต่แจ่ม
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Flask เป็น &lt;strong&gt;Microframework&lt;/strong&gt; ที่เน้นความเรียบง่าย และให้ความยืดหยุ่นสูง คุณสามารถเริ่มต้นโปรเจกต์ได้ง่ายๆ โดยไม่ต้องตั้งค่ามากมาย เหมาะกับคนที่ชอบควบคุมทุกอย่างเอง&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ข้อดีของ Flask
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;เริ่มต้นง่าย&lt;/strong&gt; เรียนรู้และใช้งานได้เร็ว เนื่องจาก Flask ไม่มีการตั้งค่าที่ซับซ้อน&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ยืดหยุ่น&lt;/strong&gt; คุณสามารถเลือกใช้เครื่องมือเสริมต่างๆ (Extensions) เพื่อเพิ่มฟีเจอร์ตามต้องการ เช่น Authentication หรือการจัดการฐานข้อมูล&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;เหมาะกับโปรเจกต์เล็ก&lt;/strong&gt; Flask เหมาะกับโปรเจกต์ที่ไม่ต้องการฟีเจอร์เยอะๆ เช่น เว็บแอปพลิเคชันที่ง่ายหรือ Microservices&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ข้อเสียของ Flask
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ต้องเพิ่มฟีเจอร์เอง&lt;/strong&gt; ถ้าคุณต้องการฟีเจอร์บางอย่าง เช่น ระบบ Admin หรือการจัดการแบบ Form Flask จะต้องใช้ Extension เสริม&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;อาจไม่เหมาะกับโปรเจกต์ใหญ่&lt;/strong&gt; ถ้าคุณกำลังทำโปรเจกต์ขนาดใหญ่ที่ต้องการฟีเจอร์ครบถ้วน Flask อาจจะไม่เหมาะเท่าไหร่&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Django – แพ็คเกจครบจบในตัว
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Django คืออะไร?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Django เป็น &lt;strong&gt;Full-stack Framework&lt;/strong&gt; ที่มาพร้อมกับฟีเจอร์ครบครัน ไม่ว่าจะเป็นระบบจัดการฐานข้อมูล, ระบบล็อกอิน, หรือเครื่องมือสำหรับจัดการ URL ก็มีมาให้ในตัว&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ข้อดีของ Django
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ครบทุกฟีเจอร์&lt;/strong&gt; Django มีทุกอย่างที่คุณต้องการในตัว เช่น ระบบ Admin, Authentication, ORM (จัดการฐานข้อมูล) และระบบ Routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ปลอดภัยสูง&lt;/strong&gt; Django มีระบบความปลอดภัยในตัว ช่วยป้องกันการโจมตีต่างๆ อย่าง SQL Injection หรือ Cross-Site Scripting&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;เหมาะกับโปรเจกต์ใหญ่&lt;/strong&gt; Django เหมาะกับโปรเจกต์ที่ต้องการความเสถียรและฟีเจอร์เยอะๆ เช่น เว็บแอปพลิเคชันขนาดใหญ่ หรือ e-commerce&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ข้อเสียของ Django
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;เรียนรู้ยากกว่า&lt;/strong&gt; ถ้าคุณเพิ่งเริ่มต้น Django อาจจะดูซับซ้อนนิดหน่อยเพราะมันมาพร้อมกับฟีเจอร์มากมาย&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;มีโครงสร้างที่ตายตัว&lt;/strong&gt; คุณอาจจะรู้สึกว่า Django ไม่ยืดหยุ่นเท่า Flask เพราะมันมีโครงสร้างที่ค่อนข้างตายตัว&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Flask vs Django – เปรียบเทียบกันหน่อย
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Flask&lt;/th&gt;
&lt;th&gt;Django&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;การเรียนรู้&lt;/td&gt;
&lt;td&gt;ง่ายและเร็ว&lt;/td&gt;
&lt;td&gt;มีความซับซ้อนแต่เข้าใจได้เร็วขึ้นเมื่อใช้งาน&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ขนาดของโปรเจกต์&lt;/td&gt;
&lt;td&gt;เหมาะกับโปรเจกต์เล็กถึงกลาง&lt;/td&gt;
&lt;td&gt;เหมาะกับโปรเจกต์ใหญ่&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ฟีเจอร์ในตัว&lt;/td&gt;
&lt;td&gt;ต้องใช้ extensions&lt;/td&gt;
&lt;td&gt;ฟีเจอร์ครบถ้วนในตัว&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ความยืดหยุ่น&lt;/td&gt;
&lt;td&gt;สูงมาก&lt;/td&gt;
&lt;td&gt;ค่อนข้างตายตัว แต่ยังปรับแต่งได้&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ความปลอดภัย&lt;/td&gt;
&lt;td&gt;ต้องเพิ่มฟีเจอร์เอง&lt;/td&gt;
&lt;td&gt;มีระบบความปลอดภัยในตัว&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  สรุป
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ถ้าคุณอยากเริ่มต้นโปรเจกต์ง่ายๆ หรืออยากสร้างเว็บแอปพลิเคชันเล็กๆ แบบไม่ต้องการตั้งค่าเยอะๆ Flask เป็นตัวเลือกที่ดี&lt;/li&gt;
&lt;li&gt;แต่ถ้าคุณกำลังทำโปรเจกต์ใหญ่ที่ต้องการฟีเจอร์ครบครันและความเสถียร Django น่าจะเหมาะกว่า&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;การเลือกใช้ Flask หรือ Django ขึ้นอยู่กับความต้องการและขนาดของโปรเจกต์ข ถ้าคุณเพิ่งเริ่มพัฒนาเว็บ แนะนำให้เริ่มจาก Flask&lt;/p&gt;

</description>
      <category>flask</category>
      <category>django</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>การจัดการสิทธิ์ไฟล์ (File Permission) ใน Linux</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Fri, 13 Jun 2025 14:07:00 +0000</pubDate>
      <link>https://dev.to/xnewz/kaarcchadkaarsiththiaifl-file-permission-ain-linux-aih</link>
      <guid>https://dev.to/xnewz/kaarcchadkaarsiththiaifl-file-permission-ain-linux-aih</guid>
      <description>&lt;p&gt;Linux มีระบบจัดการสิทธิ์ (Permission) ที่มีประสิทธิภาพ เพื่อควบคุมการเข้าถึงไฟล์และโฟลเดอร์ ระบบนี้ช่วยป้องกันการเข้าถึงโดยไม่ได้รับอนุญาตและเสริมความปลอดภัยให้กับระบบ&lt;/p&gt;

&lt;h2&gt;
  
  
  1. พื้นฐานของ Linux File Permission
&lt;/h2&gt;

&lt;p&gt;Linux ใช้ระบบสิทธิ์ 3 ระดับ คือ&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Owner (ผู้เป็นเจ้าของ)&lt;/strong&gt; คนที่สร้างไฟล์หรือโฟลเดอร์&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Group (กลุ่ม)&lt;/strong&gt; ผู้ใช้ที่อยู่ในกลุ่มเดียวกัน&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Others (อื่น ๆ)&lt;/strong&gt; ผู้ใช้ที่ไม่ได้เป็นทั้งเจ้าของหรืออยู่ในกลุ่ม&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;สิทธิ์แบ่งเป็น 3 ประเภท&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Read (r)&lt;/strong&gt; อ่านไฟล์/ดูรายชื่อไฟล์ในโฟลเดอร์&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write (w)&lt;/strong&gt; แก้ไขไฟล์/เพิ่มหรือลบไฟล์ในโฟลเดอร์&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute (x)&lt;/strong&gt; รันไฟล์ที่เป็นสคริปต์หรือโปรแกรม/เข้าโฟลเดอร์&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. การดูสิทธิ์ของไฟล์หรือโฟลเดอร์
&lt;/h2&gt;

&lt;p&gt;ใช้คำสั่ง ls -l เพื่อดูรายละเอียดไฟล์&lt;/p&gt;

&lt;p&gt;ตัวอย่างผลลัพธ์&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-rwxr-xr--&lt;/span&gt;  1 user group  2048 Jan  5  example.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;อธิบาย &lt;code&gt;-rwxr-xr--&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;-&lt;/strong&gt; ไฟล์ธรรมดา (หากเป็นโฟลเดอร์จะเป็น d)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;rwx&lt;/strong&gt; สิทธิ์ของ Owner (อ่าน, เขียน, รัน)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;r-x&lt;/strong&gt; สิทธิ์ของ Group (อ่าน, รัน)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;r--&lt;/strong&gt; สิทธิ์ของ Others (อ่านเท่านั้น)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. การเปลี่ยนสิทธิ์ของไฟล์ (chmod)
&lt;/h2&gt;

&lt;p&gt;การกำหนดด้วยตัวอักษร&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เพิ่มสิทธิ์
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;u+x example.sh  &lt;span class="c"&gt;# เพิ่มสิทธิ์รันให้ Owner&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;g+w example.txt  &lt;span class="c"&gt;# เพิ่มสิทธิ์เขียนให้ Group&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;ลบสิทธิ์
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;o-r example.txt  &lt;span class="c"&gt;# ลบสิทธิ์อ่านของ Others&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;การกำหนดด้วยเลขฐาน 8 (Octal) หรือ แบบ Numeric&lt;/p&gt;

&lt;p&gt;เลข 3 หลักแทนสิทธิ์ (r=4, w=2, x=1)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;7 (rwx)&lt;/strong&gt; มีสิทธิ์ทั้งหมด&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;6 (rw-)&lt;/strong&gt; อ่านและเขียน&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 (r-x)&lt;/strong&gt; อ่านและรัน&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4 (r--)&lt;/strong&gt; อ่านอย่างเดียว&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ตัวอย่างการใช้งาน&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;755 example.sh  &lt;span class="c"&gt;# Owner=เต็มสิทธิ์, Group=อ่าน+รัน, Others=อ่าน+รัน&lt;/span&gt;
&lt;span class="nb"&gt;chmod &lt;/span&gt;644 example.txt  &lt;span class="c"&gt;# Owner=อ่าน+เขียน, Group=อ่าน, Others=อ่าน&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  การคำนวณแบบ Numeric สำหรับสิทธิ์ของไฟล์ใน Linux
&lt;/h3&gt;

&lt;p&gt;Numeric Mode คือการใช้ตัวเลขฐานแปด (Octal) เพื่อแทนสิทธิ์ของไฟล์ใน Linux ซึ่งประกอบด้วย 3 ระดับคือ Owner, Group, และ Others&lt;br&gt;
โดยแต่ละระดับประกอบด้วยสิทธิ์ 3 ประเภท Read (r), Write (w), และ Execute (x)&lt;/p&gt;
&lt;h3&gt;
  
  
  ตารางสิทธิ์ของไฟล์ใน Linux
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;สิทธิ์&lt;/th&gt;
&lt;th&gt;คำอธิบาย&lt;/th&gt;
&lt;th&gt;ค่าเลขฐานแปด&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;r&lt;/td&gt;
&lt;td&gt;อ่าน (Read)&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;w&lt;/td&gt;
&lt;td&gt;เขียน (Write)&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td&gt;รัน (Execute)&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;ไม่มีสิทธิ์&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;วิธีคำนวณ Numeric&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;แยกสิทธิ์ออกเป็น 3 กลุ่ม Owner, Group, และ Others&lt;/li&gt;
&lt;li&gt;สำหรับแต่ละกลุ่ม

&lt;ul&gt;
&lt;li&gt;นำค่าของ r, w, x มารวมกันตามสิทธิ์ที่กำหนด&lt;/li&gt;
&lt;li&gt;ถ้าไม่มีสิทธิ์ ให้ใช้ 0&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;รวมค่าของทั้ง 3 กลุ่มเข้าด้วยกันเป็นเลข 3 หลัก&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ตัวอย่างการคำนวณ Numeric Mode&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ตัวอย่างสิทธิ์

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;-rwxr-xr--&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;แบ่งสิทธิ์&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  ตัวอย่างการคำนวณสิทธิ์ของไฟล์ใน Linux
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;กลุ่ม&lt;/th&gt;
&lt;th&gt;สิทธิ์&lt;/th&gt;
&lt;th&gt;ค่าตัวเลข&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Owner&lt;/td&gt;
&lt;td&gt;rwx&lt;/td&gt;
&lt;td&gt;4 + 2 + 1 = 7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Group&lt;/td&gt;
&lt;td&gt;r-x&lt;/td&gt;
&lt;td&gt;4 + 0 + 1 = 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Others&lt;/td&gt;
&lt;td&gt;r--&lt;/td&gt;
&lt;td&gt;4 + 0 + 0 = 4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;รวมค่าของทั้ง 3 กลุ่ม

&lt;ul&gt;
&lt;li&gt;Numeric Mode = 754&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ตัวอย่างเพิ่มเติม&lt;/p&gt;
&lt;h3&gt;
  
  
  ตัวอย่างการคำนวณสิทธิ์ของไฟล์ใน Linux
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;สิทธิ์&lt;/th&gt;
&lt;th&gt;Owner&lt;/th&gt;
&lt;th&gt;Group&lt;/th&gt;
&lt;th&gt;Others&lt;/th&gt;
&lt;th&gt;Numeric Mode&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;-rw-r--r--&lt;/td&gt;
&lt;td&gt;rw-&lt;/td&gt;
&lt;td&gt;r--&lt;/td&gt;
&lt;td&gt;r--&lt;/td&gt;
&lt;td&gt;644&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-rwx------&lt;/td&gt;
&lt;td&gt;rwx&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-rwxr-xr-x&lt;/td&gt;
&lt;td&gt;rwx&lt;/td&gt;
&lt;td&gt;r-x&lt;/td&gt;
&lt;td&gt;r-x&lt;/td&gt;
&lt;td&gt;755&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-rw-rw----&lt;/td&gt;
&lt;td&gt;rw-&lt;/td&gt;
&lt;td&gt;rw-&lt;/td&gt;
&lt;td&gt;---&lt;/td&gt;
&lt;td&gt;660&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  4. การเปลี่ยนเจ้าของและกลุ่ม (chown และ chgrp)
&lt;/h2&gt;

&lt;p&gt;เปลี่ยนเจ้าของไฟล์&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;user example.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เปลี่ยนกลุ่มของไฟล์&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chgrp &lt;/span&gt;group example.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เปลี่ยนทั้งเจ้าของและกลุ่ม&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chown &lt;/span&gt;user:group example.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. ความสำคัญของ Special Permissions
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;SetUID (s)

&lt;ul&gt;
&lt;li&gt;รันไฟล์ในฐานะเจ้าของไฟล์ ไม่ใช่ผู้รัน&lt;/li&gt;
&lt;li&gt;ใช้กับไฟล์โปรแกรม เช่น /usr/bin/passwd
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;u+s example.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;SetGID (s)

&lt;ul&gt;
&lt;li&gt;กำหนดให้ไฟล์หรือโฟลเดอร์ใหม่ในกลุ่มเดียวกัน
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;g+s folder/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Sticky Bit (t)

&lt;ul&gt;
&lt;li&gt;กำหนดให้ลบไฟล์ในโฟลเดอร์ได้เฉพาะเจ้าของ
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +t /tmp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. ตัวอย่างการตั้งค่าสิทธิ์ในสถานการณ์จริง
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;โฟลเดอร์ Public (อ่านได้ทุกคน)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;755 /var/www/html/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;ไฟล์ส่วนตัว (Owner เท่านั้นที่อ่านได้)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;600 secret.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;โฟลเดอร์ที่แชร์ในทีม
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;770 shared_folder/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  สรุป
&lt;/h2&gt;

&lt;p&gt;การจัดการ Permission ของไฟล์ใน Linux ช่วยให้ระบบมีความปลอดภัยและจัดการได้ง่ายขึ้น การเข้าใจคำสั่งพื้นฐาน เช่น chmod, chown, และ ls -l จะช่วยให้คุณสามารถบริหารจัดการสิทธิ์ได้ถูกต้อง&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
    </item>
    <item>
      <title>วิธีติดตั้งและกำหนดค่าเบื้องต้นสำหรับเซิร์ฟเวอร์ DNS บน Ubuntu 22.04 LTS แบบง่าย ๆ</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Fri, 27 Dec 2024 09:28:00 +0000</pubDate>
      <link>https://dev.to/xnewz/withiitidtangaelakamhndkhaaebuuengtnsamhrabechirfewr-dns-bn-ubuntu-2204-lts-aebbngaay--1ohk</link>
      <guid>https://dev.to/xnewz/withiitidtangaelakamhndkhaaebuuengtnsamhrabechirfewr-dns-bn-ubuntu-2204-lts-aebbngaay--1ohk</guid>
      <description>&lt;p&gt;การติดตั้งและกำหนดค่าเซิร์ฟเวอร์ DNS บนระบบปฏิบัติการ Ubuntu เป็นขั้นตอนที่สำคัญสำหรับการบริหารจัดการการแปลงชื่อโดเมนเป็นที่อยู่ IP ในเครือข่ายของคุณอย่างมีประสิทธิภาพ การทำงานของเซิร์ฟเวอร์ DNS ช่วยให้เว็บไซต์และแอปพลิเคชันของคุณสามารถถูกเข้าถึงได้โดยง่ายและมีประสิทธิภาพ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2exau9maw24gaxjwd303.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2exau9maw24gaxjwd303.png" alt="Image description" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ขั้นตอนที่ 1 ติดตั้ง BIND
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;อัปเดทและติดตั้ง BIND
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;bind9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ขั้นตอนที่ 2 กำหนดค่าตัวเลือกของ BIND
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;แก้ไขไฟล์ named.conf.options เพื่อกำหนดค่าตัวเลือกของ BIND
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/bind/named.conf.options
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;แก้ไขไฟล์ดังตัวอย่าง
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;options &lt;span class="o"&gt;{&lt;/span&gt;
    directory &lt;span class="s2"&gt;"/var/cache/bind"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    // ถ้าต้องการดึงข้อมูลจากเซิร์ฟเวอร์ DNS อื่น
    forwarders &lt;span class="o"&gt;{&lt;/span&gt;
        8.8.8.8&lt;span class="p"&gt;;&lt;/span&gt;
        8.8.4.4&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    // ที่อยู่ของ IP สำหรับการส่ง query DNS เข้ามา
    listen-on &lt;span class="o"&gt;{&lt;/span&gt; 192.168.64.33&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    // เปิดใช้งานการบันทึก query
    querylog &lt;span class="nb"&gt;yes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    // อนุญาตให้ query จาก &lt;span class="nb"&gt;local
    &lt;/span&gt;allow-query &lt;span class="o"&gt;{&lt;/span&gt; localhost&lt;span class="p"&gt;;&lt;/span&gt; 192.168.64.0/24&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ขั้นตอนที่ 3 กำหนดค่าโซนของโดเมน pargorn.com
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;แก้ไขข้อมูลโซน
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/bind/named.conf.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;เพิ่มข้อมูลโซน
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zone &lt;span class="s2"&gt;"pargorn.com"&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;type &lt;/span&gt;master&lt;span class="p"&gt;;&lt;/span&gt;
    file &lt;span class="s2"&gt;"/etc/bind/db.pargorn.com"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ขั้นตอนที่ 4 สร้างไฟล์โซนของโดเมน pargorn.com
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;คัดลอกไฟล์ และแก้ไขไฟล์
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /etc/bind/db.local /etc/bind/db.pargorn.com
&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/bind/db.pargorn.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;แก้ไขไฟล์ db.pargorn.com
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$TTL&lt;/span&gt;    604800
@       IN      SOA     ns.pargorn.com. root.pargorn.com. &lt;span class="o"&gt;(&lt;/span&gt;
                              1         &lt;span class="p"&gt;;&lt;/span&gt; Serial
                         604800         &lt;span class="p"&gt;;&lt;/span&gt; Refresh
                          86400         &lt;span class="p"&gt;;&lt;/span&gt; Retry
                        2419200         &lt;span class="p"&gt;;&lt;/span&gt; Expire
                         604800 &lt;span class="o"&gt;)&lt;/span&gt;       &lt;span class="p"&gt;;&lt;/span&gt; Negative Cache TTL
&lt;span class="p"&gt;;&lt;/span&gt;
@       IN      NS      ns.pargorn.com.
ns      IN      A       192.168.64.33
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;บันทึกและปิดไฟล์
### ขั้นตอนที่ 5 รีสตาร์ท BIND&lt;/li&gt;
&lt;li&gt;รีสตาร์ท BIND เพื่อนำการเปลี่ยนแปลงไปใช้
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart bind9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ขั้นตอนที่ 6 เพิ่ม DNS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เพิ่ม DNS IP Address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4tqrfqljulxzolap9yu.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4tqrfqljulxzolap9yu.gif" alt="Image description" width="1024" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6muauuzg5dru48r1556w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6muauuzg5dru48r1556w.png" alt="Image description" width="800" height="910"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ขั้นตอนที่ 7 ทดสอบ DNS
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ใช้เครื่องมือเช่น nslookup หรือ dig เพื่อทดสอบ DNS
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nslookup ns.pargorn.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqr86qo9u1a664ilaccyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqr86qo9u1a664ilaccyq.png" alt="Image description" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;เราได้ทำการติดตั้งและกำหนดค่าเซิร์ฟเวอร์ DNS บน Ubuntu เรียบร้อยแล้ว คุณสามารถปรับแต่งตามความต้องการของคุณได้ตามต้องการ&lt;/p&gt;

</description>
      <category>ubuntu</category>
      <category>linux</category>
      <category>dns</category>
    </item>
    <item>
      <title>SQL Injection คืออะไร? และวิธีการป้องกัน</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Thu, 26 Dec 2024 06:52:00 +0000</pubDate>
      <link>https://dev.to/xnewz/sql-injection-khuueaair-aelawithiikaarpngkan-2dll</link>
      <guid>https://dev.to/xnewz/sql-injection-khuueaair-aelawithiikaarpngkan-2dll</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv74virdyu467m9pebq6i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv74virdyu467m9pebq6i.jpg" alt="Image description" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  SQL Injection
&lt;/h1&gt;

&lt;p&gt;เป็นการโจมตีด้านความปลอดภัยที่พบได้บ่อยในระบบฐานข้อมูลที่ใช้ SQL (Structured Query Language) เป็นภาษาสำหรับการจัดการฐานข้อมูล การโจมตีนี้เกิดจากการที่ Attacker ใส่โค้ด SQL ที่เป็นอันตรายลงในช่องทางการป้อนข้อมูลของผู้ใช้ เช่น ช่องกรอกแบบฟอร์ม หรือ URL เพื่อเข้าถึงหรือแก้ไขข้อมูลในฐานข้อมูลอย่างไม่ถูกต้อง&lt;/p&gt;

&lt;p&gt;SQL Injection จัดอยู่อันดับที่ 3 ใน &lt;a href="https://owasp.org/www-project-top-ten/" rel="noopener noreferrer"&gt;OWASP Top 10&lt;/a&gt; ปี 2021 ซึ่งเป็นรายการของช่องโหว่ความปลอดภัยที่พบบ่อยและสำคัญที่สุดสำหรับเว็บแอปพลิเคชันที่จัดทำโดย Open Web Application Security Project (OWASP) รายการนี้มีการปรับปรุงทุกๆ หลายปีเพื่อสะท้อนถึงการเปลี่ยนแปลงของภัยคุกคามทางไซเบอร์&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpashgrzsymp3tra496xy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpashgrzsymp3tra496xy.png" alt="Image description" width="800" height="220"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;การโจมตีแบบ SQL Injection นั้นถูกจัดเป็นภัยคุกคามอันดับ 3 แสดงให้เห็นถึงความสำคัญและความแพร่หลายของปัญหานี้ในแง่ของความปลอดภัยของเว็บแอปพลิเคชัน การจัดการกับการโจมตีแบบ Injection อย่างถูกวิธีเป็นสิ่งจำเป็นในการรักษาความปลอดภัยของระบบข้อมูลและป้องกันการเข้าถึงที่ไม่พึงประสงค์&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  วิธีการโจมตี SQL Injection
&lt;/h2&gt;

&lt;p&gt;การโจมตี SQL Injection สามารถทำได้หลากหลายรูปแบบ แต่หลักๆ จะมีสองวิธีที่พบได้บ่อย ได้แก่&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;การใส่ค่าเข้าไปในช่องทางป้อนข้อมูลโดยตรง&lt;/li&gt;
&lt;li&gt;การแก้ไข URL เพื่อเพิ่มคำสั่ง SQL&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ตัวอย่างการโจมตี SQL Injection
&lt;/h2&gt;

&lt;p&gt;สมมติว่ามีเว็บแอปพลิเคชันที่ให้ผู้ใช้เข้าสู่ระบบ โดยมีโค้ด PHP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_POST&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_POST&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"SELECT * FROM users WHERE username='&lt;/span&gt;&lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="s2"&gt;' AND password='&lt;/span&gt;&lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mysqli_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mysqli_num_rows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Login successful!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Invalid username or password."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;โค้ดนี้มีช่องโหว่เนื่องจากการใส่ค่าจากผู้ใช้เข้าไปในคำสั่ง SQL โดยตรง ทำให้เกิด SQL Injection ได้&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  การโจมตีโดยใช้ SQL Injection
&lt;/h2&gt;

&lt;p&gt;แฮกเกอร์สามารถใส่ค่าที่เป็นอันตรายลงในช่องกรอกข้อมูล ดังนี้&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ช่อง username&lt;/strong&gt; &lt;code&gt;' OR '1'='1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ช่อง password&lt;/strong&gt; &lt;code&gt;' OR '1'='1&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ซึ่งจะทำให้คำสั่ง SQL เป็นดังนี้&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="s1"&gt;'1'&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;เนื่องจาก '1'='1' เป็นเงื่อนไขที่เป็นจริงเสมอ คำสั่งนี้จะส่งคืนข้อมูลของผู้ใช้ทุกคนในฐานข้อมูล ทำให้แฮกเกอร์สามารถเข้าสู่ระบบได้โดยไม่ต้องใช้รหัสผ่านจริง&lt;/p&gt;

&lt;h1&gt;
  
  
  วิธีการป้องกัน SQL Injection
&lt;/h1&gt;

&lt;p&gt;มีหลายวิธีที่สามารถป้องกัน SQL Injection ได้ เช่น&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;การใช้ Prepared Statements&lt;/li&gt;
&lt;li&gt;การใช้ Stored Procedures&lt;/li&gt;
&lt;li&gt;การกรองและตรวจสอบข้อมูลที่ป้อนเข้ามา
## ตัวอย่างการใช้ Prepared Statements ใน PHP
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="nv"&gt;$stmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$conn&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prepare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"SELECT * FROM users WHERE username=? AND password=?"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$stmt&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;bind_param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"ss"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_POST&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nv"&gt;$password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_POST&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nv"&gt;$stmt&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$stmt&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get_result&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;num_rows&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Login successful!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Invalid username or password."&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="cp"&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;ในตัวอย่างนี้ คำสั่ง SQL จะถูกเตรียมไว้ล่วงหน้า และค่า $username และ $password จะถูกใส่เข้าไปในคำสั่งนี้ภายหลัง ทำให้ไม่สามารถใส่โค้ด SQL ที่เป็นอันตรายเข้าไปได้&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  สรุป
&lt;/h1&gt;

&lt;p&gt;SQL Injection เป็นภัยคุกคามที่ร้ายแรง แต่สามารถป้องกันได้ด้วยการเขียนโค้ดที่มีความปลอดภัย เช่น การใช้ Prepared Statements และการตรวจสอบข้อมูลที่ป้อนเข้ามา การป้องกันที่ดีไม่เพียงแต่ช่วยรักษาความปลอดภัยของข้อมูล แต่ยังช่วยรักษาความน่าเชื่อถือของระบบอีกด้วย&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>php</category>
      <category>sql</category>
    </item>
    <item>
      <title>ทำความเข้าใจเกี่ยวกับ Big-O และตัวอย่างโค้ดในภาษา C++</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Wed, 25 Dec 2024 07:10:00 +0000</pubDate>
      <link>https://dev.to/xnewz/thamkhwaamekhaaaicchekiiywkab-big-o-aelatawyaangokhdainphaasaa-c-mc2</link>
      <guid>https://dev.to/xnewz/thamkhwaamekhaaaicchekiiywkab-big-o-aelatawyaangokhdainphaasaa-c-mc2</guid>
      <description>&lt;h2&gt;
  
  
  Big-O Notation
&lt;/h2&gt;

&lt;p&gt;เป็นวิธีการในการวิเคราะห์และแสดงประสิทธิภาพของอัลกอริธึม โดยจะพิจารณาจากจำนวนขั้นตอนการทำงานหรือเวลาที่ใช้ในการทำงานเมื่อขนาดของข้อมูลเพิ่มขึ้น โดยไม่สนใจปัจจัยคงที่หรือเงื่อนไขที่ไม่เปลี่ยนแปลงเมื่อขนาดข้อมูลเปลี่ยนไป Big-O ช่วยให้เราเปรียบเทียบอัลกอริธึมต่าง ๆ และเลือกอัลกอริธึมที่เหมาะสมสำหรับงานที่ต้องการ&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbgibnkgy6yhk9rdaq68.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbgibnkgy6yhk9rdaq68.jpeg" alt="Image description" width="800" height="556"&gt;&lt;/a&gt;&lt;br&gt;
กราฟ Big-O ใช้เพื่อแสดงให้เห็นถึงความสัมพันธ์ระหว่างขนาดของข้อมูล (n) และเวลาในการประมวลผลหรือจำนวนขั้นตอนการทำงานของอัลกอริธึม โดยเส้นโค้งของกราฟจะแสดงถึงการเติบโตของเวลาในการทำงานเมื่อขนาดของข้อมูลเพิ่มขึ้น นี่คือลักษณะของกราฟ Big-O สำหรับประเภทต่าง ๆ ของอัลกอริธึมที่กล่าวถึงไป&lt;/p&gt;

&lt;h3&gt;
  
  
  O(1) - Constant Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เส้นกราฟจะเป็นเส้นตรงแนวนอน ซึ่งหมายความว่าเวลาในการทำงานไม่เปลี่ยนแปลงตามขนาดของข้อมูล
&amp;gt; การเข้าถึงค่าในอาร์เรย์โดยใช้เลขดัชนี (Index)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;constantTimeExample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;  &lt;span class="c1"&gt;// O(1)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O(log n) - Logarithmic Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เส้นกราฟจะเป็นเส้นโค้งที่ค่อย ๆ เพิ่มขึ้น โดยมีอัตราการเพิ่มที่ลดลงเรื่อย ๆ&lt;/li&gt;
&lt;li&gt;Binary Search
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;binarySearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// O(log n)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;เติบโตช้าเมื่อขนาดข้อมูลเพิ่มขึ้น&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  O(n) - Linear Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เส้นกราฟจะเป็นเส้นตรงที่เพิ่มขึ้นตามขนาดของข้อมูล&lt;/li&gt;
&lt;li&gt;Linear Search
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;linearSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// O(n)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;เติบโตเป็นเส้นตรงตามขนาดข้อมูล&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  O(n log n) - Linearithmic Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เส้นกราฟจะเพิ่มขึ้นตามขนาดข้อมูลแบบไม่เป็นเส้นตรง และเร็วกว่าการเติบโตแบบเชิงเส้น&lt;/li&gt;
&lt;li&gt;Merge Sort และ Quick Sort
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Merge two halves&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;mergeSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;mergeSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// O(n log n)&lt;/span&gt;
        &lt;span class="n"&gt;mergeSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;เติบโตเร็วกว่า O(n) แต่ช้ากว่า O(n^2)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  O(n^2) - Quadratic Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เส้นกราฟจะเป็นเส้นโค้งที่เติบโตเร็วขึ้นตามขนาดข้อมูล&lt;/li&gt;
&lt;li&gt;Bubble Sort
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;  &lt;span class="c1"&gt;// O(n^2)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;เติบโตเร็วขึ้นเรื่อย ๆ ตามขนาดข้อมูล&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  O(2^n) - Exponential Time
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;เส้นกราฟจะเป็นเส้นโค้งที่เติบโตอย่างรวดเร็วมาก ตามขนาดข้อมูลที่เพิ่มขึ้น&lt;/li&gt;
&lt;li&gt;Fibonacci Recursive
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// O(2^n)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;เติบโตเร็วมากจนอาจไม่สามารถใช้งานได้เมื่อขนาดข้อมูลใหญ่&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ความสัมพันธ์ของ Big-O
&lt;/h2&gt;

&lt;p&gt;ลองจินตนาการถึงกราฟที่แสดงค่า Big-O ต่าง ๆ โดยแกน x แทนขนาดของข้อมูล (n) และแกน y แทนเวลาในการประมวลผล&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O(1) เส้นตรงแนวนอนที่ค่าคงที่&lt;/li&gt;
&lt;li&gt;O(log n) เส้นโค้งที่ค่อย ๆ เพิ่มขึ้นในอัตราลดลง (เช่น เส้นโค้งลอการิทึม)&lt;/li&gt;
&lt;li&gt;O(n) เส้นตรงที่เพิ่มขึ้นอย่างสมมาตร&lt;/li&gt;
&lt;li&gt;O(n log n) เส้นโค้งที่เพิ่มขึ้นอย่างรวดเร็วขึ้นจาก O(n) แต่ช้ากว่า O(n^2)&lt;/li&gt;
&lt;li&gt;O(n^2) เส้นโค้งพาราโบลาที่เพิ่มขึ้นอย่างรวดเร็ว&lt;/li&gt;
&lt;li&gt;O(2^n) เส้นโค้งที่เติบโตอย่างรวดเร็วมาก คล้ายเส้นเอ็กซ์โพเนนเชียล&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  สรุป
&lt;/h2&gt;

&lt;p&gt;Big-O Notation เป็นเครื่องมือสำคัญในการวิเคราะห์และเปรียบเทียบประสิทธิภาพของอัลกอริธึม โดยช่วยให้เราสามารถตัดสินใจเลือกอัลกอริธึมที่มีประสิทธิภาพเหมาะสมกับงานที่ต้องการ โดยการเข้าใจประเภทต่าง ๆ ของ Big-O&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>cpp</category>
    </item>
    <item>
      <title>สร้าง Dashboard ด้วย Grafana และ InfluxDB ด้วย Docker บน Ubuntu</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Tue, 24 Dec 2024 07:07:00 +0000</pubDate>
      <link>https://dev.to/xnewz/sraang-dashboard-dwy-grafana-aela-influxdb-dwy-docker-bn-ubuntu-2do</link>
      <guid>https://dev.to/xnewz/sraang-dashboard-dwy-grafana-aela-influxdb-dwy-docker-bn-ubuntu-2do</guid>
      <description>&lt;p&gt;ในบทความนี้เราจะมาสร้าง Dashboard ด้วย Grafana และ InfluxDB ด้วย Docker บน Ubuntu กัน !!!&lt;br&gt;
ก่อนอื่นเรามาทำความรู้จักกับ Grafana และ InfluxDB กันก่อนครับ และเราจะใช้ Docker ในการสร้าง Container ของ Grafana และ InfluxDB&lt;/p&gt;

&lt;h2&gt;
  
  
  ทำความรู้จักกับ Grafana และ InfluxDB
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e4ms6qxbctdfjle65rx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8e4ms6qxbctdfjle65rx.png" alt="Image description" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Grafana
&lt;/h3&gt;

&lt;p&gt;เป็นแพลตฟอร์มที่ใช้ในการสร้างแดชบอร์ด (dashboard) สำหรับการแสดงผลข้อมูลจากแหล่งข้อมูลหลายๆ แห่ง&lt;br&gt;
มีความสามารถในการสร้างภาพกราฟิกส์แบบต่างๆ ไม่ว่าจะเป็นกราฟเส้น กราฟแท่ง แผนภูมิ และแผนที่&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobwljg19uazit8pelcg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fobwljg19uazit8pelcg7.png" alt="Image description" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  InfluxDB
&lt;/h3&gt;

&lt;p&gt;เป็นฐานข้อมูลที่ออกแบบมาเพื่อการจัดเก็บและจัดการข้อมูลที่เกิดขึ้นตามเวลา (time series data) โดยเฉพาะ&lt;br&gt;
ไม่ว่าจะเป็นข้อมูลจากเซนเซอร์, log data, หรือ metrics จากระบบคอมพิวเตอร์&lt;br&gt;
InfluxDB มีความสามารถในการจัดการข้อมูลจำนวนมหาศาลได้อย่างรวดเร็วและมีประสิทธิภาพ&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;InfluxDB มีภาษา query ของตัวเองที่คล้ายกับ SQL ทำให้ง่ายต่อการใช้งานและการเรียนรู้&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  ตัวอย่างภาษา query ของ InfluxDB
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;เราสามารถเลือกข้อมูลในช่วงเวลาที่ต้องการ เช่น ข้อมูลอุณหภูมิในช่วง 24 ชั่วโมงที่ผ่านมา
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;เราสามารถใช้ฟังก์ชันเชิงรวมเพื่อคำนวณค่าเฉลี่ย, ค่าสูงสุด, หรือต่ำสุดของข้อมูลได้ เช่น คำนวณค่าเฉลี่ยของอุณหภูมิในช่วง 24 ชั่วโมงที่ผ่านมา
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;MEAN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;เราสามารถจัดกลุ่มข้อมูลตามเวลาเพื่อดูการเปลี่ยนแปลงของข้อมูลในแต่ละช่วงเวลา เช่น ค่าเฉลี่ยของอุณหภูมิทุกๆ 1 ชั่วโมง ในช่วง 24 ชั่วโมงที่ผ่านมา
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;MEAN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ตัวอย่างภาษา query ของ InfluxDB รูปแบบ Flux
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Flux เป็นภาษา query ใหม่ของ influxdb
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from(bucket: "mydb/autogen")
  |&amp;gt; range(start: -1h)
  |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "cpu")
  |&amp;gt; filter(fn: (r) =&amp;gt; r.cpu == "cpu-total")
  |&amp;gt; aggregateWindow(every: 1m, fn: mean, createEmpty: false)
  |&amp;gt; yield(name: "mean")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;query นี้ดึงข้อมูลจาก bucket &lt;code&gt;mydb/autoge&lt;/code&gt; ในช่วง 1 ชั่วโมงที่ผ่านมา โดยกรองข้อมูลที่มี &lt;code&gt;_measurement&lt;/code&gt; เป็น "cpu" และ cpu เป็น "cpu-total" จากนั้นคำนวณค่าเฉลี่ยทุก ๆ 1 นาที และส่งผลลัพธ์ออกมาด้วยชื่อ "mean"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ขั้นตอนการติดตั้ง
&lt;/h2&gt;

&lt;h3&gt;
  
  
  อัปเดตแพคเกจของ Ubuntu
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ติดตั้ง Docker บน Ubuntu
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Set up apt repository
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add Docker's official GPG key:&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;ca-certificates curl
&lt;span class="nb"&gt;sudo install&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; 0755 &lt;span class="nt"&gt;-d&lt;/span&gt; /etc/apt/keyrings
&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg &lt;span class="nt"&gt;-o&lt;/span&gt; /etc/apt/keyrings/docker.asc
&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+r /etc/apt/keyrings/docker.asc

&lt;span class="c"&gt;# Add the repository to Apt sources:&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"deb [arch=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;dpkg &lt;span class="nt"&gt;--print-architecture&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
  &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; /etc/os-release &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$VERSION_CODENAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;ติดตั้ง Docker packages
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;ตรวจสอบการติดตั้ง Docker
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;ถ้าหากใช้คำสั่ง &lt;code&gt;sudo docker --version&lt;/code&gt; แล้วขึ้นเลขเวอร์ชันของ Docker แสดงว่าการติดตั้งสำเร็จ&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  การติดตั้ง และสร้างไฟล์ Docker Compose
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ติดตั้ง Docker Compose
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/docker/compose/releases/latest/download/docker-compose-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/local/bin/docker-compose
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;ตรวจสอบการติดตั้ง Docker Compose
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;สร้างไฟล์ &lt;code&gt;docker-compose.yml&lt;/code&gt; ด้วยคำสั่ง
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;แก้ไขไฟล์ &lt;code&gt;docker-compose.yml&lt;/code&gt; ด้วยโปรแกรมที่ต้องการ เช่น nano, vim, หรือ Visual Studio Code
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;แก้ไขไฟล์ &lt;code&gt;docker-compose.yml&lt;/code&gt; ด้วยโค้ดด้านล่าง
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.1'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;influxdb&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;influxdb:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;influxdb&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8086:8086"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;INFLUXDB_DB=mydatabase&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;INFLUXDB_ADMIN_USER=admin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;INFLUXDB_ADMIN_PASSWORD=adminpassword&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;influxdb-data:/var/lib/influxdb&lt;/span&gt;

  &lt;span class="na"&gt;grafana&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana/grafana:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;GF_SECURITY_ADMIN_USER=admin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;GF_SECURITY_ADMIN_PASSWORD=adminpassword&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;grafana-data:/var/lib/grafana&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;influxdb-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;grafana-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  รัน Container ด้วย Docker Compose
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;รันคำสั่งเพื่อสร้าง Container จากไฟล์ &lt;code&gt;docker-compose.yml&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;-d&lt;/code&gt; คือคำสั่งที่ใช้ในการรัน Container ในโหมด background (จะรัน Container ตลอดเวลา)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs058ei5h37y86ot4fun.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbs058ei5h37y86ot4fun.png" alt="Image description" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  การตั้งค่า InfluxDB
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;หลังจากที่ Container ของ InfluxDB รันเสร็จแล้ว ให้เข้าไปที่ &lt;code&gt;http://localhost:8086&lt;/code&gt; หรือ &lt;code&gt;http://server-ip:8086&lt;/code&gt; ในเว็บเบราวเซอร์&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9giny4j89txuqgy2cppg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9giny4j89txuqgy2cppg.png" alt="Image description" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ตั้งค่า Username, Password, Organization, Bucket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz65r4tvvakkj5i5zqiww.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz65r4tvvakkj5i5zqiww.png" alt="Image description" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เมื่อตั้งค่าเสร็จแล้ว คุณจะได้ API Token มา ให้เก็บไว้เพื่อใช้ในการเชื่อมต่อกับ Grafana&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqqllvf601nyboxfj0lc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqqllvf601nyboxfj0lc.png" alt="Image description" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  การตั้งค่า Grafana
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;เข้าไปที่ &lt;code&gt;http://localhost:3000&lt;/code&gt; หรือ &lt;code&gt;http://server-ip:8086&lt;/code&gt; ในเว็บเบราวเซอร์
แล้วเข้าสู่ระบบด้วยข้อมูลผู้ใช้ &lt;code&gt;admin&lt;/code&gt; และรหัสผ่าน &lt;code&gt;adminpassword&lt;/code&gt; ที่ได้กำหนดไว้ในไฟล์ docker-compose.yml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdozjhn4cswg9abgu1mxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdozjhn4cswg9abgu1mxi.png" alt="Image description" width="800" height="816"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  เพิ่ม Data Source
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ให้ไปที่ &lt;code&gt;Connection&lt;/code&gt; -&amp;gt; &lt;code&gt;Data Source&lt;/code&gt; แล้วเลือก &lt;code&gt;InfluxDB&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsufr0z6cp280v0ow8qoo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsufr0z6cp280v0ow8qoo.png" alt="Image description" width="800" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เลือก Query Language เป็น &lt;code&gt;Flux&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyr2ph4vntwsk7dui6pa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyr2ph4vntwsk7dui6pa.png" alt="Image description" width="800" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ตั้งค่า URL ให้เป็น &lt;code&gt;http://localhost:8086&lt;/code&gt; หรือ &lt;code&gt;http://server-ip:8086&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vgxinphr5q8scsrnb5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vgxinphr5q8scsrnb5a.png" alt="Image description" width="800" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เปิดใช้งาน Basic Auth และกรอก Username และ Password ให้ตรงกับที่ได้ตั้งค่าใน docker-compose.yml&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F448rctomamdt2x3xwquu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F448rctomamdt2x3xwquu.png" alt="Image description" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;กรอกข้อมูล Organization, Bucket, Token ที่ได้จากการตั้งค่า InfluxDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn0t7bqljrn1tbxe3clgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn0t7bqljrn1tbxe3clgc.png" alt="Image description" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;คลิก &lt;code&gt;Save &amp;amp; Test&lt;/code&gt; เพื่อทดสอบการเชื่อมต่อ&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnjpd5zobpv1fee0i3jq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnjpd5zobpv1fee0i3jq.png" alt="Image description" width="800" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ถ้าหากขึ้นข้อความ &lt;code&gt;Data source is working&lt;/code&gt; แสดงว่าการเชื่อมต่อสำเร็จ !!!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  สร้าง Dashboard
&lt;/h2&gt;

&lt;h3&gt;
  
  
  สร้าง Dashboard ใหม่
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;ให้ไปที่เมนู &lt;code&gt;Dashboards&lt;/code&gt; -&amp;gt; &lt;code&gt;Create Dashboard&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2begqc449tusysddw6u6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2begqc449tusysddw6u6.png" alt="Image description" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;กด &lt;code&gt;Add visualization&lt;/code&gt; เพื่อเพิ่มกราฟ และเลือก &lt;code&gt;Data Source&lt;/code&gt; ที่เราตั้งค่าไว้&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F434392c84k3hnw618a5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F434392c84k3hnw618a5k.png" alt="Image description" width="800" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ช่องสำหรับเขียน Query เพื่อดึงข้อมูลจาก InfluxDB มาแสดงผลเป็นกราฟ&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2eloh6v1nzy7c9p6vrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2eloh6v1nzy7c9p6vrq.png" alt="Image description" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  เพิ่มข้อมูลใน InfluxDB เพื่อทดสอบ
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;หลักจากที่เราได้ตั้งค่าทุกอย่างเสร็จเรียบร้อยแล้ว ให้เข้าไปที่ &lt;code&gt;http://localhost:8086&lt;/code&gt; หรือ &lt;code&gt;http://server-ip:8086&lt;/code&gt; ในเว็บเบราวเซอร์
เพื่อเข้าไปเพิ่มข้อมูลใน InfluxDB ของเรากัน&lt;/li&gt;
&lt;li&gt;ตอนนี้ Bucket ของเราจะว่างเปล่าอยู่ ให้เราเพิ่มข้อมูลเข้าไปเพื่อนำไปแสดงผลใน Grafana&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ให้กดที่ &lt;code&gt;Data Explorer&lt;/code&gt; แล้วเลือก &lt;code&gt;Bucket&lt;/code&gt; ที่เราตั้งค่าไว้ และกดไปที่ &lt;code&gt;Script Editor&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8p3q9f9csdw8ka21ojmx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8p3q9f9csdw8ka21ojmx.png" alt="Image description" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ใช้สคริปต์ Flux เพื่อเพิ่มข้อมูลจำลองเข้าไปใน Bucket ของเรา
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "experimental"
import "array"

data = array.from(rows: [
  {_time: experimental.addDuration(d: -10m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 1},
  {_time: experimental.addDuration(d: -9m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 2},
  {_time: experimental.addDuration(d: -8m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 3},
  {_time: experimental.addDuration(d: -7m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 4},
  {_time: experimental.addDuration(d: -6m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 5},
  {_time: experimental.addDuration(d: -5m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 6},
  {_time: experimental.addDuration(d: -4m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 7},
  {_time: experimental.addDuration(d: -3m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 8},
  {_time: experimental.addDuration(d: -2m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 9},
  {_time: experimental.addDuration(d: -1m, to: now()), _measurement: "measurement", tag1: "value1", _field: "field1", _value: 10}
])

data
  |&amp;gt; to(bucket: "test")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;สคริปต์นี้จะสร้างข้อมูลจำลอง 10 แถวใน bucket &lt;code&gt;test&lt;/code&gt; โดยมีเวลาเป็นช่วงเวลาที่แตกต่างกันภายใน 10 นาทีที่ผ่านมา และค่า field1 เป็นตัวเลขตั้งแต่ 1 ถึง 10&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;หลังจากนั้นกด &lt;code&gt;Submit&lt;/code&gt; เพื่อเพิ่มข้อมูลเข้าไปใน Bucket&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0f13ahx3ho5715nh58id.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0f13ahx3ho5715nh58id.png" alt="Image description" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;เมื่อไม่มีอะไรผิดพลาดขึ้น ข้อมูลจะถูกเพิ่มเข้าไปใน Bucket ของเรา และจะแสดงเส้นกราฟใน Data Explorer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhe4o3sa1pivev77qevh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhe4o3sa1pivev77qevh.png" alt="Image description" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Query ข้อมูลจาก InfluxDB ใน Grafana
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;ให้เพิ่มคำสั่ง Query ใน Visualization ของเรา
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from(bucket: "test")
  |&amp;gt; range(start: -1h)
  |&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "measurement")
  |&amp;gt; filter(fn: (r) =&amp;gt; r.tag1 == "value1")
  |&amp;gt; aggregateWindow(every: 1m, fn: mean, createEmpty: false)
  |&amp;gt; yield(name: "mean")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjesg3kw1mq6e2ndudkn1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjesg3kw1mq6e2ndudkn1.png" alt="Image description" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  อธิบายการทำงานของคำสั่ง
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;from(bucket: "test")&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;เลือก bucket ชื่อ &lt;code&gt;test&lt;/code&gt; เป็นแหล่งข้อมูลเริ่มต้นที่จะทำการ query&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;|&amp;gt; range(start: -1h)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;กำหนดช่วงเวลาของข้อมูลที่ต้องการดึงมา โดยจะดึงข้อมูลตั้งแต่ 1 ชั่วโมงที่ผ่านมาจนถึงปัจจุบัน&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-1h&lt;/code&gt; หมายถึง 1 ชั่วโมงที่ผ่านมาจากเวลาปัจจุบัน&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;|&amp;gt; filter(fn: (r) =&amp;gt; r._measurement == "measurement")&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;กรองข้อมูลให้เหลือเฉพาะที่ &lt;code&gt;_measurement&lt;/code&gt; มีค่าเป็น "measurement"&lt;/li&gt;
&lt;li&gt;ฟังก์ชั่น &lt;code&gt;filter&lt;/code&gt; จะทำการประเมินเงื่อนไข &lt;code&gt;fn: (r) =&amp;gt; r._measurement == "measurement"&lt;/code&gt; โดย &lt;code&gt;r&lt;/code&gt; คือแต่ละแถวของข้อมูล&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;|&amp;gt; filter(fn: (r) =&amp;gt; r.tag1 == "value1")&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;กรองข้อมูลเพิ่มเติมให้เหลือเฉพาะที่ &lt;code&gt;tag1&lt;/code&gt; มีค่าเป็น "value1"&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;|&amp;gt; aggregateWindow(every: 1m, fn: mean, createEmpty: false)&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;ทำการรวมข้อมูลในช่วงเวลาที่กำหนดโดยใช้ฟังก์ชั่น &lt;code&gt;mean&lt;/code&gt; (ค่าเฉลี่ย)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;every: 1m&lt;/code&gt; หมายถึงช่วงเวลา 1 นาที&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;createEmpty: false&lt;/code&gt; หมายถึงไม่สร้างช่วงเวลาที่ไม่มีข้อมูล&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;|&amp;gt; yield(name: "mean")&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;ส่งผลลัพธ์ออกมาโดยใช้ชื่อ "mean"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yield&lt;/code&gt;เป็นคำสั่งที่บอกให้ query สิ้นสุดและส่งผลลัพธ์&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  ตัวอย่างตารางของข้อมูล
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;_time&lt;/th&gt;
&lt;th&gt;_value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2024-06-01T12:00:00Z&lt;/td&gt;
&lt;td&gt;10.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024-06-01T12:01:00Z&lt;/td&gt;
&lt;td&gt;11.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024-06-01T12:02:00Z&lt;/td&gt;
&lt;td&gt;10.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  บันทึกการตั้งค่า
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;กด &lt;code&gt;Apply&lt;/code&gt; เพื่อบันทึกการตั้งค่า&lt;/li&gt;
&lt;li&gt;เราก็จะได้ข้อมูลจาก InfluxDB มาแสดงผลใน Grafana เรียบร้อย&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;คุณสามารถเปลี่ยนรูปแบบของกราฟได้โดยกดไปที่ &lt;code&gt;Visualization&lt;/code&gt; และเลือกรูปแบบที่ต้องการ&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8o6q0vl6v496n1ohbsd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8o6q0vl6v496n1ohbsd.png" alt="Image description" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  สรุป
&lt;/h2&gt;

&lt;p&gt;ในบทความนี้เราได้เรียนรู้วิธีการสร้าง Dashboard ด้วย Grafana และ InfluxDB ด้วย Docker บน Ubuntu&lt;br&gt;
และเราได้ทำการตั้งค่าและเชื่อมต่อ Grafana กับ InfluxDB และสร้าง Dashboard แสดงผลข้อมูลจาก InfluxDB ได้เรียบร้อย ไว้เจอกันใน Blog ต่อไปครับ 👋👋👋&lt;/p&gt;

</description>
      <category>docker</category>
      <category>grafana</category>
      <category>influxdb</category>
      <category>devops</category>
    </item>
    <item>
      <title>วิธีทำ Auth API ด้วย Express, JWT, MySQL และ Prisma</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Tue, 24 Dec 2024 06:55:00 +0000</pubDate>
      <link>https://dev.to/xnewz/withiitham-auth-api-dwy-express-jwt-mysql-aela-prisma-4abi</link>
      <guid>https://dev.to/xnewz/withiitham-auth-api-dwy-express-jwt-mysql-aela-prisma-4abi</guid>
      <description>&lt;p&gt;การสร้าง Auth API ด้วย JWT และ MySQL โดยใช้ Prisma สำหรับการจัดการฐานข้อมูล&lt;br&gt;
จะมีการแยกส่วนประกอบออกเป็นไฟล์ต่างๆ เพื่อความสะดวกในการแก้ไข&lt;br&gt;
โดยในตัวอย่างนี้ เราจะใช้ Node.js กับ Express.js สำหรับ backend และ JWT สำหรับการจัดการ token&lt;br&gt;
พร้อมด้วย Prisma สำหรับการจัดการกับฐานข้อมูล MySQL&lt;/p&gt;
&lt;h2&gt;
  
  
  ขั้นตอนการติดตั้งและตั้งค่า
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;auth-api
&lt;span class="nb"&gt;cd &lt;/span&gt;auth-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  สร้างโปรเจค Node.js และติดตั้ง package ที่ใช้
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;express prisma @prisma/client jsonwebtoken bcryptjs body-parser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ตั้งค่า Prisma
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ตั้งค่าไฟล์ Prisma schema
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;prisma/schema.prisma
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

model User {
  id       Int      @id @default(autoincrement())
  username String   @unique
  password String
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ตั้งค่าไฟล์ .env
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;user&lt;/code&gt; ชื่อผู้ใช้ของ MySQL&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;password&lt;/code&gt; รหัสผ่านของ MySQL&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;localhost:3306&lt;/code&gt; ที่อยู่ของ MySQL&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auth_db&lt;/code&gt; ชื่อฐานข้อมูลที่จะใช้
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATABASE_URL="mysql://user:password@localhost:3306/auth_db"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  สร้างฐานข้อมูลและตาราง
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma migrate dev &lt;span class="nt"&gt;--name&lt;/span&gt; init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  สร้างไฟล์และโฟลเดอร์ต่างๆ
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;server.js config.js routes.js
&lt;span class="nb"&gt;mkdir &lt;/span&gt;controllers models middlewares
&lt;span class="nb"&gt;touch &lt;/span&gt;controllers/authController.js middlewares/middleware.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  โครงสร้างโปรเจค
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auth-api/
├── controllers/
│   └── authController.js
├── middlewares/
│   └── middleware.js
├── models/
│   └── userModel.js
├── prisma/
│   ├── migrations/
│   │   └── &amp;lt;migration files&amp;gt;
│   ├── schema.prisma
├── .env
├── config.js
├── package.json
├── routes.js
├── server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  เขียนโค้ดสำหรับแต่ละไฟล์
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;server.js
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน express เพื่อสร้าง server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน body-parser เพื่อแปลงข้อมูลที่ส่งมาให้เป็น JSON&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./routes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งานไฟล์ routes.js ที่เราสร้างไว้เพื่อใช้ในการกำหนดเส้นทางของ API&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// สร้าง instance ของ express&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// กำหนด port ที่จะใช้ในการรัน server&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// ใช้ body-parser ในการแปลงข้อมูลที่ส่งมาให้เป็น JSON&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// กำหนดเส้นทางของ API&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// รัน server ที่ port ที่กำหนด&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server is running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;config.js
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;jwtSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-secret-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// กำหนด secret key สำหรับการสร้าง token&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;models/userModel.js
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน PrismaClient จาก @prisma/client&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// สร้าง instance ของ PrismaClient&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bcryptjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน bcryptjs เพื่อใช้ในการเข้ารหัสรหัสผ่าน&lt;/span&gt;

&lt;span class="c1"&gt;// สร้างผู้ใช้ใหม่&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// เข้ารหัสรหัสผ่านก่อนที่จะเก็บไว้ในฐานข้อมูล&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// บันทึกข้อมูลผู้ใช้ลงในฐานข้อมูล&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;hash&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// ค้นหาผู้ใช้จากชื่อผู้ใช้&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;findUserByUsername&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;findUserByUsername&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;controllers/authController.js
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน jwt เพื่อใช้ในการสร้าง token&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bcryptjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน bcryptjs เพื่อใช้ในการเข้ารหัสรหัสผ่าน&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งานไฟล์ config.js ที่เราสร้างไว้&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../models/userModel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน userModel.js ที่เราสร้างไว้&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;register&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// รับข้อมูล username และ password จาก body ของ request&lt;/span&gt;
    &lt;span class="c1"&gt;// สร้างผู้ใช้ใหม่&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createUser&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User registered successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// หากเกิดข้อผิดพลาดในการสร้างผู้ใช้&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error registering user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;login&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// รับข้อมูล username และ password จาก body ของ request&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findUserByUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ค้นหาผู้ใช้จากชื่อผู้ใช้&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// หากไม่พบผู้ใช้&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid username or password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// หากรหัสผ่านไม่ตรงกับที่เก็บไว้ในฐานข้อมูล&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;bcrypt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isMatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Invalid username or password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c1"&gt;// สร้าง token และส่งกลับไปให้ผู้ใช้&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwtSecret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;expiresIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1h&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// หากเกิดข้อผิดพลาดในการเข้าสู่ระบบ&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error logging in&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;login&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;middlewares/middleware.js
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jsonwebtoken&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน jwt เพื่อใช้ในการตรวจสอบ token&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งานไฟล์ config.js ที่เราสร้างไว้&lt;/span&gt;

&lt;span class="c1"&gt;// next คือ callback function ที่ใช้ในการส่งต่อไปยัง middleware ถัดไป&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verifyToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// middleware สำหรับตรวจสอบ token&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// รับ token จาก header ของ request&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;403&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No token provided&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// หากไม่มี token ให้ส่งข้อความกลับไปว่าไม่มี token&lt;/span&gt;

    &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwtSecret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// ตรวจสอบ token&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to authenticate token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// หากไม่สามารถตรวจสอบ token ได้ให้ส่งข้อความกลับไปว่าไม่สามารถตรวจสอบ token ได้&lt;/span&gt;

        &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ถ้าตรวจสอบ token สำเร็จ ให้เก็บ id ของผู้ใช้ไว้ใน req.userId&lt;/span&gt;
        &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ส่งต่อไปยัง middleware ถัดไป&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;verifyToken&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;routes.js
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน express&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authController&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./controllers/authController&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน authController.js ที่เราสร้างไว้&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./middlewares/middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// เรียกใช้งาน middleware.js ที่เราสร้างไว้&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// สร้าง instance ของ express.Router&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/register&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// สร้างเส้นทางสำหรับการลงทะเบียนผู้ใช้&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;authController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;login&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// สร้างเส้นทางสำหรับการเข้าสู่ระบบ&lt;/span&gt;

&lt;span class="c1"&gt;// Protected route example&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/protected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;verifyToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// สร้างเส้นทางสำหรับการตรวจสอบ token&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;This is a protected route&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// ส่งข้อความกลับไปว่านี่คือเส้นทางที่ถูกป้องกัน&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  รัน server
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;เราสามารถทดสอบ API ด้วย Postman หรือ Thunder Client โดยการสร้าง request ไปที่ &lt;code&gt;http://localhost:3000/api/register&lt;/code&gt; และ &lt;code&gt;http://localhost:3000/api/login&lt;/code&gt; และส่งข้อมูล username และ password ไปด้วย&lt;/p&gt;
&lt;h3&gt;
  
  
  ตัวอย่าง request สำหรับ route register
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;/api/register
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john_doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password123"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Response
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User registered successfully"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ตัวอย่าง request สำหรับ route login
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;/api/login
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john_doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password123"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Response
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"token-string"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ตัวอย่าง request สำหรับ route protected
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;/api/protected
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ใส่&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ใน&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ของ&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"token-string"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Response
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is a protected route"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;นอกจากนี้เรายังสามารถใช้งาน Prisma Studio เพื่อดูข้อมูลในฐานข้อมูลได้ด้วย&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma studio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;สามารถดูตัวอย่างโค้ดทั้งหมดได้จาก &lt;a href="https://github.com/xNewz/auth-api-mysql-prisma" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;br&gt;
หรือสามารถดูตัวอย่างการทำงานได้จาก &lt;a href="https://www.youtube.com/watch?v=WERrX2NjBEA&amp;amp;t=198s" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;&lt;/p&gt;

</description>
      <category>express</category>
      <category>mysql</category>
      <category>prisma</category>
      <category>jwt</category>
    </item>
    <item>
      <title>การทำ HTTPS ด้วย Certbot และ Nginx บน Ubuntu Server</title>
      <dc:creator>Pargorn Ruasijan</dc:creator>
      <pubDate>Tue, 24 Dec 2024 06:44:00 +0000</pubDate>
      <link>https://dev.to/xnewz/kaartham-https-dwy-certbot-aela-nginx-bn-ubuntu-server-4f9i</link>
      <guid>https://dev.to/xnewz/kaartham-https-dwy-certbot-aela-nginx-bn-ubuntu-server-4f9i</guid>
      <description>&lt;p&gt;การรักษาความปลอดภัยของเว็บไซต์เป็นสิ่งสำคัญอย่างยิ่งในยุคดิจิทัลปัจจุบัน โดยเฉพาะการใช้โปรโตคอล HTTPS ซึ่งช่วยให้ข้อมูลที่ส่งผ่านเว็บไซต์ของคุณถูกเข้ารหัสและปลอดภัย&lt;br&gt;
ในบทความนี้เราจะมาสอนวิธีการติดตั้งและกำหนดค่า HTTPS บนเซิร์ฟเวอร์ Ubuntu ด้วย Certbot และ Nginx&lt;/p&gt;

&lt;h4&gt;
  
  
  สิ่งที่ต้องมี
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;เซิร์ฟเวอร์ Ubuntu&lt;/strong&gt; แนะนำ Ubuntu 20.04 LTS หรือเวอร์ชันล่าสุด&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nginx&lt;/strong&gt; หากยังไม่มี สามารถติดตั้งได้ตามขั้นตอนในบทความนี้&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;โดเมนเนมที่ชี้ไปยังเซิร์ฟเวอร์ของคุณ&lt;/strong&gt; เช่น example.com และมี DNS records ชี้ไปยัง IP ของเซิร์ฟเวอร์&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;สิทธิ์การเข้าถึงแบบ root&lt;/strong&gt; หรือผู้ใช้ที่มีสิทธิ์ sudo บนเซิร์ฟเวอร์&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  วิธีการชี้โดเมนไปยัง IP ของเซิร์ฟเวอร์
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;เพิ่ม DNS records สำหรับโดเมน certbot.pargorn.com ที่ชี้ไปยัง IP ของเซิร์ฟเวอร์&lt;/li&gt;
&lt;li&gt;เลือก &lt;code&gt;A record&lt;/code&gt; และใส่ IP ของเซิร์ฟเวอร์&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ขั้นตอนที่ 1 อัปเดตระบบ
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;เริ่มต้นด้วยการอัปเดตแพคเกจของระบบให้เป็นเวอร์ชันล่าสุด
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ขั้นตอนที่ 2 ติดตั้ง Nginx
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;หากยังไม่ได้ติดตั้ง Nginx สามารถติดตั้งได้ด้วยคำสั่ง
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;หลังจากติดตั้งเสร็จสิ้น ตรวจสอบให้แน่ใจว่า Nginx ทำงานอยู่&lt;/li&gt;
&lt;li&gt;คุณควรเห็นสถานะ &lt;code&gt;active (running)&lt;/code&gt; ถ้า Nginx ทำงานถูกต้อง&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbgrcckqrsiv4fqd5173.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbgrcckqrsiv4fqd5173.png" alt="Image description" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ขั้นตอนที่ 3 สร้างเว็บไซต์ “Hello Certbot”
&lt;/h4&gt;

&lt;p&gt;เราจะสร้างเว็บไซต์ง่ายๆ ที่แสดงข้อความ “Hello Certbot” สำหรับโดเมน &lt;code&gt;certbot.pargorn.com&lt;/code&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  1. สร้างไดเรกทอรีสำหรับเว็บไซต์
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /var/www/certbot.pargorn.com/html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  2. กำหนดสิทธิ์ให้กับไดเรกทอรี
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt;:&lt;span class="nv"&gt;$USER&lt;/span&gt; /var/www/certbot.pargorn.com/html
&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; 755 /var/www/certbot.pargorn.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  3. สร้างไฟล์ HTML สำหรับเว็บไซต์
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;สร้างไฟล์ index.html ที่จะแสดงข้อความ “Hello Certbot”
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano /var/www/certbot.pargorn.com/html/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  4. จากนั้นเพิ่มเนื้อหาดังนี้
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;บันทึกไฟล์โดยกด &lt;code&gt;Ctrl + O&lt;/code&gt; แล้วออกจาก nano ด้วย &lt;code&gt;Ctrl + X&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Hello Certbot&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Hello Certbot&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  5. สร้างไฟล์การตั้งค่าเซิร์ฟเวอร์สำหรับ Nginx
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;สร้างไฟล์การตั้งค่าสำหรับเว็บไซต์ &lt;code&gt;certbot.pargorn.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/nginx/sites-available/certbot.pargorn.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  6. เพิ่มเนื้อหาดังนี้
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;บันทึกไฟล์โดยกด &lt;code&gt;Ctrl + O&lt;/code&gt; แล้วออกจาก nano ด้วย &lt;code&gt;Ctrl + X&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;certbot.pargorn.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/certbot.pargorn.com/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt; &lt;span class="s"&gt;index.htm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  7. เปิดใช้งานการตั้งค่าเว็บไซต์
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;สร้าง symbolic link ไปยัง sites-enabled เพื่อเปิดใช้งานเว็บไซต์
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; /etc/nginx/sites-available/certbot.pargorn.com /etc/nginx/sites-enabled/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  8. ทดสอบการตั้งค่าของ Nginx
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzw6vbdjgdrpj177pd1y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnzw6vbdjgdrpj177pd1y.png" alt="Image description" width="800" height="81"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  9. หากไม่มีข้อผิดพลาด ให้รีสตาร์ท Nginx
&lt;/h5&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  10. ตรวจสอบว่าเว็บไซต์ “Hello Certbot” ทำงานอยู่หรือไม่
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;เปิดเว็บเบราว์เซอร์และเข้าไปที่ &lt;code&gt;http://certbot.pargorn.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ขั้นตอนที่ 4 ติดตั้ง Certbot
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Certbot เป็นเครื่องมือที่ช่วยให้การขอและต่ออายุ SSL Certificates จาก Let’s Encrypt เป็นเรื่องง่าย ในการติดตั้ง Certbot สำหรับ Nginx บน Ubuntu
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ขั้นตอนที่ 5 ขอรับ SSL Certificate ด้วย Certbot
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;หลังจากติดตั้งเสร็จสิ้น สามารถใช้ Certbot ในการขอรับ SSL Certificate ได้โดยใช้คำสั่ง
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; certbot.pargorn.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Certbot จะถามข้อมูลต่างๆ ดังนี้&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;อีเมลสำหรับการแจ้งเตือน&lt;/strong&gt; ใส่อีเมลที่สามารถติดต่อได้เพื่อรับการแจ้งเตือนเกี่ยวกับ SSL Certificate&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ยอมรับข้อตกลงการให้บริการ&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;เลือกโดเมนที่ต้องการเปิดใช้งาน HTTPS&lt;/strong&gt; ในที่นี้จะเลือก &lt;code&gt;certbot.pargorn.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;เลือกว่าจะทำการเปลี่ยนเส้นทางทั้งหมดจาก HTTP เป็น HTTPS หรือไม่&lt;/strong&gt; แนะนำให้เลือกให้เปลี่ยนเส้นทางทั้งหมด&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  ตัวอย่าง
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Which names would you like to activate HTTPS for?
- certbot.pargorn.com

Please choose whether or not to redirect HTTP traffic to HTTPS,
removing HTTP access. Your web traffic will then only be available
through HTTPS.

1: No redirect - Make no further changes to the webserver configuration
2: Redirect - Make all requests redirect to secure HTTPS access.
   Choose this for simple HTTPS setups.

Select the appropriate number [1-2] then [enter] (default: 2):
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ขั้นตอนที่ 6 ตรวจสอบการตั้งค่า Nginx
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Certbot จะปรับแต่งไฟล์การตั้งค่า Nginx ให้รองรับ HTTPS โดยอัตโนมัติ แต่คุณสามารถตรวจสอบได้ที่ไฟล์การตั้งค่าใน /etc/nginx/sites-available/certbot.pargorn.com
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;certbot.pargorn.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;301&lt;/span&gt; &lt;span class="s"&gt;https://&lt;/span&gt;&lt;span class="nv"&gt;$host$request_uri&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;certbot.pargorn.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/certbot.pargorn.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/certbot.pargorn.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;include&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/options-ssl-nginx.conf&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_dhparam&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/ssl-dhparams.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/certbot.pargorn.com/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt; &lt;span class="s"&gt;index.htm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;หลังจากตรวจสอบแล้ว ให้ทดสอบการตั้งค่าของ Nginx
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;ถ้าการตั้งค่าถูกต้อง ให้รีสตาร์ท Nginx
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  ขั้นตอนที่ 7 ทดสอบเว็บไซต์ด้วย HTTPS
&lt;/h4&gt;

&lt;p&gt;เปิดเว็บเบราว์เซอร์และเข้าไปที่ &lt;code&gt;https://certbot.pargorn.com&lt;/code&gt; คุณควรเห็น &lt;code&gt;ไอคอนรูปกุญแจล็อก 🔒&lt;/code&gt; ที่แสดงถึงการเชื่อมต่อที่ปลอดภัย พร้อมทั้งหน้าเว็บที่แสดงข้อความ “Hello Certbot” หากไม่มีข้อผิดพลาดใดๆ เกิดขึ้น แสดงว่าการตั้งค่า HTTPS สำเร็จเรียบร้อยแล้ว&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrhwdp24f0i9fzr3a2b3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnrhwdp24f0i9fzr3a2b3.png" alt="Image description" width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ขั้นตอนที่ 8 ตั้งค่าการต่ออายุอัตโนมัติสำหรับ SSL Certificate
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;SSL Certificates จาก Let’s Encrypt มีอายุ 90 วัน คุณสามารถตั้งค่าให้ Certbot ต่ออายุอัตโนมัติได้ด้วยการเพิ่ม Cron Job หรือใช้ systemd timer ที่มาพร้อมกับ Certbot&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ตรวจสอบให้แน่ใจว่า Cron Job สำหรับ Certbot มีอยู่&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl list-timers | &lt;span class="nb"&gt;grep &lt;/span&gt;certbot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bfqxlh37b4a7wuuva5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bfqxlh37b4a7wuuva5g.png" alt="Image description" width="800" height="32"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;โดยปกติ Certbot จะตั้งค่าให้ทำการตรวจสอบและต่ออายุอัตโนมัติทุกวัน หากต้องการตรวจสอบการต่ออายุสามารถทำได้ด้วยคำสั่ง&lt;/li&gt;
&lt;li&gt;ถ้าไม่มีข้อผิดพลาด แสดงว่าการตั้งค่าการต่ออายุอัตโนมัติทำงานได้ถูกต้อง
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;certbot renew &lt;span class="nt"&gt;--dry-run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  สรุป
&lt;/h4&gt;

&lt;p&gt;การติดตั้งและกำหนดค่า HTTPS บน Nginx ด้วย Certbot บน Ubuntu Server เป็นกระบวนการที่ไม่ซับซ้อนและสามารถทำได้ในไม่กี่ขั้นตอน การใช้ HTTPS จะช่วยเพิ่มความปลอดภัยให้กับเว็บไซต์ของคุณและสร้างความเชื่อมั่นให้กับผู้ใช้งาน ในบทความนี้เราได้สร้างเว็บไซต์ที่แสดงข้อความ “Hello Certbot” และใช้โดเมน certbot.pargorn.com เพื่อแสดงให้เห็นถึงการตั้งค่าอย่างครบถ้วน อย่าลืมตรวจสอบและต่ออายุ SSL Certificates อย่างสม่ำเสมอเพื่อรักษาความปลอดภัยของเว็บไซต์อย่างต่อเนื่อง&lt;/p&gt;

&lt;h4&gt;
  
  
  อ้างอิง
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://certbot.eff.org/" rel="noopener noreferrer"&gt;เอกสาร Certbot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ubuntu.com/tutorials/install-and-configure-nginx" rel="noopener noreferrer"&gt;คู่มือการติดตั้ง Nginx บน Ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://letsencrypt.org/" rel="noopener noreferrer"&gt;ข้อมูลเกี่ยวกับ SSL Certificates จาก Let’s Encrypt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ubuntu</category>
      <category>nginx</category>
      <category>certbot</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
