จัดการ Secrets ใน Docker โดยไม่ฝังรหัสผ่านไว้ใน Image
แยก API key, database password และข้อมูลลับออกจาก Dockerfile และ source code พร้อมแนวทางใช้ environment, secret file และ secret manager ให้เหมาะกับ production

ภาพรวม
Docker ใช้งานง่าย แต่หลายโปรเจกต์พลาดตรง “เก็บความลับผิดที่” จนข้อมูลสำคัญหลุดโดยไม่รู้ตัว 🔐🐳
สิ่งที่ควรจำให้ขึ้นใจคือ ENV ไม่ได้ถูกออกแบบมาเพื่อเก็บความลับระดับสำคัญเสมอไป
หลายคนใส่ทุกอย่างลงไปใน .env แล้วจบ ทั้ง API key, database password, token, private key วิธีนี้สะดวกมาก แต่ก็เสี่ยงมากเหมือนกัน ⚠️
ENV เหมาะกับ “ค่าคอนฟิกทั่วไป” ที่แอปต้องรู้ตอนรัน เช่น PORT, APP_ENV, LOG_LEVEL, FEATURE_FLAG, BASE_URL ค่าพวกนี้หลุดแล้วมักไม่ถึงขั้นระบบพังทั้งก้อน
แต่ถ้าเป็นข้อมูลที่ใช้ยืนยันตัวตน หรือเปิดทางเข้าระบบ เช่น DB_PASSWORD, JWT_SECRET, API_TOKEN, SSH_KEY พวกนี้ควรแยกจาก ENV ปกติให้ชัดเจน 🧩
Docker Secrets ถูกสร้างมาเพื่อโจทย์นี้โดยเฉพาะ มันช่วยเก็บข้อมูลสำคัญแยกจาก image และไม่ควร hardcode ใน source code 🚫💻
ข้อดีที่หลายคนไม่รู้คือ secret มักถูก mount เข้า container เป็นไฟล์ ไม่ใช่แปะตรงๆ เป็น environment variable จึงลดโอกาสหลุดผ่าน log, process list หรือ debug tool ได้ระดับหนึ่ง 🛡️
ตัวอย่างแนวคิดง่ายๆ APP_ENV=production PORT=8080 LOG_LEVEL=info สามตัวนี้ใส่ ENV ได้สบาย
แต่ถ้าเป็น DB_PASSWORD=supersecret STRIPE_SECRET_KEY=... JWT_SECRET=... สามตัวนี้ควรย้ายไปฝั่ง secret มากกว่า
อีกจุดที่พลาดกันบ่อยมากคือ build argument บางคนส่ง secret ผ่าน ARG ตอน docker build แล้วคิดว่าปลอดภัย ความจริงมันอาจหลงเหลือใน image layer หรือ history ได้ 😵💫
ถ้าต้องใช้ secret ระหว่าง build ควรใช้วิธีที่รองรับ secret โดยตรง เช่น BuildKit secrets แทนการฝังค่าลง Dockerfile ตรงๆ
ENV ยังมีข้อจำกัดอีกอย่าง เวลามีคนเข้า shell ใน container แล้วรันคำสั่ง env ค่าหลายอย่างอาจถูกเห็นได้ทันที 👀
หรือถ้าแอป crash แล้ว dump environment ลง log ความลับก็ออกสู่โลกภายนอกได้แบบไม่ตั้งใจ
แนวทางแยกง่ายๆ จำแบบนี้ได้เลย ✨
ใส่ใน ENV เมื่อเป็น ค่าคอนฟิกทั่วไป ค่าที่เปลี่ยนตาม environment ค่าที่ไม่ได้ใช้พิสูจน์ตัวตน ค่าที่หลุดแล้วความเสียหายต่ำ
ใส่ใน Secret เมื่อเป็น รหัสผ่าน access token private key certificate key credential ที่เข้าถึงบริการอื่นได้ ข้อมูลที่มีกฎ compliance กำกับ
อีกเรื่องที่สำคัญไม่แพ้กัน อย่า commit ไฟล์ .env ที่มีค่าจริงขึ้น Git เด็ดขาด 🚫📦 ถึง repo จะ private ก็ยังไม่ควรชะล่าใจ เพราะความผิดพลาดจากการแชร์สิทธิ์เกิดขึ้นได้เสมอ
แนวทางที่ดีคือมี .env.example สำหรับบอกชื่อคีย์ แต่ไม่ใส่ค่าจริง เช่น DB_HOST= DB_NAME= DB_USER= DB_PASSWORD=
ทีมงานจะรู้ว่าต้องตั้งค่าอะไรบ้าง แต่ค่าจริงให้ดึงจากระบบจัดการ secret ของแต่ละ environment
ถ้าทำงานกับ Docker Compose หลายคนใช้ env_file เพื่อความสะดวก ใช้ได้กับค่าคอนฟิกทั่วไป แต่ถ้าเป็นความลับระดับ production ควรมีชั้นป้องกันมากกว่านั้น 🔒
ในระบบใหญ่ขึ้นไป อาจขยับไปใช้เครื่องมืออย่าง Docker Swarm secrets, Kubernetes Secrets, Vault หรือ cloud secret manager ☁️
ประเด็นสำคัญไม่ได้อยู่ที่ “ห้ามใช้ ENV” แต่อยู่ที่ “ต้องรู้ว่าอะไรเป็น config และอะไรเป็น secret”
ถ้าแยกสองอย่างนี้ไม่ชัด วันหนึ่งระบบอาจไม่ได้โดนแฮกจากโค้ดพัง แต่อาจพังจากการเก็บข้อมูลผิดที่แทน 💥
สรุปสั้นแบบพร้อมใช้ 📌 ENV ใช้กับค่าตั้งค่าทั่วไปของระบบ Secrets ใช้กับข้อมูลลับที่ห้ามหลุด อย่า hardcode อย่า commit ค่าจริง อย่าส่ง secret ผ่าน build แบบมั่วๆ และอย่าคิดว่า .env ปลอดภัยโดยอัตโนมัติ
คนที่แยก config ออกจาก secret ได้ดี มักดูแลระบบ production ได้นิ่งกว่าแบบเห็นชัดเจน 🧠🐳
แนวทางนำไปใช้
- นำแนวคิดจากโพสต์นี้ไปทดลองกับงานจริงของคุณ
- แยกเป็นขั้นตอนเล็ก ๆ แล้วทำทีละส่วน
- บันทึกผลลัพธ์และสิ่งที่เรียนรู้เพื่อต่อยอด
สรุป
แยก API key, database password และข้อมูลลับออกจาก Dockerfile และ source code พร้อมแนวทางใช้ environment, secret file และ secret manager ให้เหมาะกับ production