
ติดตั้ง Langfuse ด้วย Docker Compose: เปิดได้ไม่พอ ต้องสำรอง trace ด้วย

การติดตั้ง Langfuse บน VM ด้วย Docker Compose ยังไม่จบเมื่อเปิดหน้าเว็บได้ เพราะ คู่มือติดตั้งของ Langfuse ระบุว่าชุด Compose ไม่มีระบบสำรองข้อมูล ความพร้อมใช้งานสูง หรือการขยายระบบในตัว ทีมที่ต้องเก็บประวัติ trace จึงต้องเตรียมทั้งทางรับข้อมูลและทางกู้คืนก่อนส่งงานจริงเข้าระบบ
ลำดับที่ใช้เป็นเกณฑ์ก่อนเปิดใช้งานคือเลือกไฟล์ Compose และ image รุ่นที่แน่นอน เปลี่ยน secret จำกัดพอร์ต ส่ง trace ทดสอบ แล้วสำรอง Postgres, ClickHouse และ object storage ในรอบที่สัมพันธ์กัน จากนั้นกู้ข้อมูลบนเครื่องแยกให้พบ trace เดิมพร้อมรายละเอียด และส่ง trace ใหม่ได้ การเห็นหน้าเข้าสู่ระบบยืนยันเพียงว่าเว็บเริ่มทำงาน ไม่ได้ยืนยันว่าข้อมูลที่เคยรับจะกลับมาได้
เริ่มจากไฟล์ Compose ที่สร้างซ้ำได้
เตรียม VM ที่ติดตั้ง Docker กับ Compose plugin และจัดพื้นที่ดิสก์ตามปริมาณ trace ที่คาดว่าจะเก็บ ดึงไฟล์ docker-compose.yml จาก repository ของ Langfuse แล้วบันทึก release หรือ commit ที่ใช้ไว้กับการตั้งค่าของเครื่อง หากดึงไฟล์จากสาขาที่เปลี่ยนต่อเนื่องโดยไม่จดรุ่น การสร้าง VM ใหม่ภายหลังอาจได้โครงสร้างบริการต่างจากเครื่องเดิม
ตรวจ image ของ langfuse-web และ langfuse-worker ให้ใช้ release เดียวกัน และเปลี่ยน tag ที่ติดตามรุ่นใหม่โดยอัตโนมัติเป็น tag ที่ทีมเลือกไว้ บันทึกรุ่นของ Postgres, ClickHouse, Redis และ MinIO ในชุดเดียวกันด้วย ก่อนอัปเกรดให้สำรองและอ่านขั้นตอนย้ายข้อมูลของรุ่นปลายทาง เพราะการนำ image เก่ากลับมาอย่างเดียวไม่ได้ย้อนการเปลี่ยนโครงสร้างฐานข้อมูลที่เกิดขึ้นแล้ว
ข้อมูลถาวรควรอยู่ใน named volumes หรือบริการจัดเก็บภายนอกที่ระบุชัด ตรวจชื่อ volume จริงด้วย docker compose config และ docker volume ls ก่อนเขียนงานสำรอง ชื่อบนโฮสต์อาจมีคำนำหน้าจากชื่อโครงการ Compose; สคริปต์ที่อ้างชื่อจาก YAML โดยเดาเองจึงอาจสำรอง volume ผิดก้อน เก็บไฟล์ Compose ที่ใช้จริงกับบันทึกรุ่นไว้ใกล้แผนกู้คืน เพื่อให้เครื่องทดสอบเริ่มจากการตั้งค่าชุดเดียวกับเครื่องต้นทาง
เปลี่ยน secret และจำกัดทางเข้าของ VM

แทนค่าตัวอย่างที่ทำเครื่องหมาย CHANGEME ทั้งรหัสผ่าน Postgres, ClickHouse, Redis และ MinIO รวมถึง NEXTAUTH_SECRET, SALT และ ENCRYPTION_KEY ด้วยค่าที่สุ่มแยกกัน ตรวจให้รหัสผ่านใน DATABASE_URL และค่าที่ web กับ worker ใช้ตรงกับบริการปลายทาง ค่าเชื่อมต่อ object storage สำหรับ event และ media ต้องตรงกับบัญชีที่ตั้งไว้ใน MinIO ด้วย เก็บค่าเหล่านี้ในระบบจัดการ secret หรือไฟล์ .env ที่จำกัดสิทธิ์ และกันไฟล์ค่าจริงออกจาก Git
ถ้า reverse proxy อยู่บน VM เดียวกัน ให้รับ HTTPS ที่ proxy แล้วผูกพอร์ตเว็บของ Langfuse กับ 127.0.0.1 ตั้ง NEXTAUTH_URL เป็น URL แบบ HTTPS ที่ผู้ใช้เปิดจริง ส่วนพอร์ต Postgres, ClickHouse, Redis และ worker ให้เข้าถึงได้เฉพาะในเครื่องหรือเครือข่ายที่จำเป็น ต้องคิดถึง MinIO แยกจากพอร์ตฐานข้อมูล: เมื่อเบราว์เซอร์ต้องรับส่งไฟล์สื่อโดยตรง ปลายทางใน LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT ต้องเป็น HTTPS ที่เบราว์เซอร์เข้าถึงได้ หากผูก MinIO ไว้ที่ loopback ให้จัดเส้นทางผ่าน proxy สำหรับงานนี้ด้วย
ตัวอย่างค่าใน compose.override.yaml แบบ YAML บรรทัดเดียวสำหรับกรณีที่ proxy อยู่บน VM เดียวกันคือ services: {langfuse-web: {image: 'docker.langfuse.com/langfuse/langfuse:${LANGFUSE_VERSION}', ports: !override ['127.0.0.1:3000:3000']}, langfuse-worker: {image: 'docker.langfuse.com/langfuse/langfuse-worker:${LANGFUSE_VERSION}'}, minio: {ports: !override ['127.0.0.1:9090:9000', '127.0.0.1:9091:9001']}} ตั้ง LANGFUSE_VERSION ใน .env เป็น release tag ที่เลือก แล้วปรับเส้นทาง MinIO ให้เข้ากับวิธีให้บริการไฟล์สื่อของทีม
กติกาการรวมไฟล์ของ Docker ระบุว่า !override ใช้แทนรายการ ports เดิมได้ตั้งแต่ Docker Compose รุ่น 2.24.4; หากเพิ่ม ports ในไฟล์ override โดยไม่ใช้วิธีนี้ พอร์ตเดิมอาจยังเปิดอยู่ ตรวจรุ่น Compose และผลรวมด้วย docker compose config ก่อนสั่ง docker compose up -d จากนั้นดูพอร์ตที่เผยแพร่จริงด้วย docker compose ps และตรวจ firewall ของ VM อีกครั้ง
ตรวจเส้นทางของ trace ก่อนรับข้อมูลจริง
หลังเริ่มบริการ ให้ดูสถานะ web, worker และ datastore ทุกตัว สร้างผู้ใช้ องค์กร โครงการ และ API key ของโครงการใน Langfuse แล้วให้แอปพลิเคชันทดสอบส่ง trace ไปยัง URL ของ instance นี้ ใช้ข้อมูลทดสอบที่ไม่มีความลับและตั้งชื่อ trace ให้ค้นหาได้แน่นอน หาก SDK เก็บข้อมูลรอส่ง ให้สั่ง flush หรือรอจนส่งเสร็จก่อนตัดสินว่าระบบไม่รับข้อมูล
เกณฑ์ผ่านคือค้น trace ที่ส่งได้ในโครงการที่ถูกต้อง เปิด observation แล้วตรวจชื่อและเวลาของคำขอให้ตรงกัน การเปิดหน้า Tracing โดยยังไม่เห็นรายการทดสอบไม่ใช่ผลผ่าน หากข้อมูลไม่ปรากฏ ให้ตรวจ URL และ API key ที่แอปใช้ก่อน แล้วไล่สถานะ worker, Redis และ ClickHouse ต่อ การแยกเส้นทางเช่นนี้ช่วยระบุว่าข้อมูลติดอยู่ตั้งแต่ฝั่งผู้ส่ง คิวประมวลผล หรือฐานข้อมูล trace
กำหนดด้วยว่าจะบันทึก prompt คำตอบ และ metadata ระดับใดก่อนรับข้อมูลลูกค้า เพราะสิ่งที่เข้า trace จะถูกนำไปอยู่ในชุดสำรองด้วย สำหรับทีมที่ใช้ OpenTelemetry ร่วมกัน การ จำกัดข้อมูลลับใน trace เป็นการตัดสินใจที่ควรเกิดก่อนเริ่มเก็บข้อมูลจริง ไม่ใช่หลังคัดลอกข้อมูลไปยังที่สำรองแล้ว
สำรอง Postgres, ClickHouse และ object storage เป็นชุดเดียว
แนวทางสำรองข้อมูลของ Langfuse ระบุว่า ClickHouse เก็บข้อมูลสังเกตการณ์อย่าง trace, observation และ score ส่วน Postgres เก็บข้อมูลธุรกรรมอย่างผู้ใช้ โครงการ และ API key และชุด Compose มี MinIO สำหรับ object storage ข้อมูลแต่ละส่วนมีหน้าที่ต่างกัน: กู้โครงการกลับมาได้แต่ไม่มี trace หรือกู้ trace ได้แต่ขาด object ที่เกี่ยวข้อง ก็ยังไม่ใช่การกู้ระบบครบชุด
- Postgres: ทำ logical dump ด้วย pg_dump หรือใช้ snapshot ที่รองรับการกู้คืน บันทึกชื่อฐานข้อมูล รุ่นของเครื่องมือ และวิธีนำข้อมูลกลับ ตรวจรหัสจบงานและตรวจว่าไฟล์สำรองมีข้อมูลก่อนนับว่ารอบนั้นสำเร็จ
- ClickHouse: ใช้ native backup หรือ snapshot ที่สอดคล้องกัน หากคัดลอก volume ตามวิธีสำหรับ Docker ให้หยุด ClickHouse ก่อนคัดลอก อย่าถือว่าสำเนาไฟล์ที่ฐานข้อมูลกำลังเขียนอยู่เป็นหลักฐานว่ากู้คืนได้
- MinIO หรือ object storage ภายนอก: สำรอง bucket ที่ Langfuse ใช้สำหรับ event และ media พร้อมโครงสร้าง path และสิทธิ์เข้าถึง หากย้ายไปใช้บริการภายนอก ให้รวมกลไกสำรองและการกู้คืนของบริการนั้นไว้ในแผน แทนการสำรองเฉพาะ volume บน VM
กำหนดจุดตัดของแต่ละรอบให้ชัดก่อนเก็บสำเนา แจ้งแอปให้หยุดส่งข้อมูลชั่วคราวหรือเลือกช่วงพักงาน รอให้คิวที่ worker กำลังประมวลผลระบายออก แล้วจึงเก็บ Postgres, ClickHouse และ object storage พร้อมบันทึกเวลาของชุดนั้น หากมีงานค้างใน Redis ระหว่างตัดรอบ ต้องถือว่าข้อมูลส่วนนั้นอาจอยู่นอกจุดกู้คืน แม้ไฟล์สำรองของ datastore อื่นจะสมบูรณ์
เก็บสำเนาอย่างน้อยหนึ่งชุดนอก VM ต้นทางและแยกสิทธิ์เข้าถึงจากบัญชีที่รันแอป กำหนดอายุเก็บรักษาตามช่วงข้อมูลที่ธุรกิจต้องย้อนดู พร้อมแจ้งเตือนเมื่อรอบสำรองล้มเหลวหรือไม่ได้สร้างไฟล์ตามเวลา เก็บ secret ที่จำเป็นต่อการกู้คืนในที่ปลอดภัยแยกจากชุดข้อมูล และบันทึกว่าชุดใดใช้กับไฟล์ Compose และ image รุ่นใด วิธีนี้ช่วยลดการลองผิดลองถูกเมื่อ VM ต้นทางใช้การไม่ได้
ซ้อม restore จนเปิด trace เดิมและรับ trace ใหม่ได้

กู้ข้อมูลบน VM หรือสภาพแวดล้อมแยกที่ไม่แตะข้อมูลจริง เริ่มจากไฟล์ Compose, image รุ่นเดิม และ secret ที่สัมพันธ์กับข้อมูลสำรอง แล้วนำ Postgres, ClickHouse และ object storage กลับมาตามวิธีของแต่ละระบบ จึงค่อยเริ่ม web กับ worker หลีกเลี่ยง docker compose down -v บนเครื่องที่ต้องรักษาข้อมูล เพราะตัวเลือกนี้ลบ named volumes ของชุด Compose
ก่อนรอบสำรอง ให้จดรหัส trace ทดสอบที่มี observation และไฟล์สื่อหากระบบใช้งานส่วนนี้ หลัง restore ให้เข้าสู่โครงการเดิม ค้น trace ด้วยรหัสนั้น เปิด observation และตรวจว่าไฟล์สื่อยังเรียกดูได้ จากนั้นส่ง trace ใหม่อีกครั้งและรอให้ปรากฏในโครงการเดิม การตรวจทั้งข้อมูลเก่าและข้อมูลใหม่แสดงว่าความสัมพันธ์ระหว่าง datastore กลับมา และเส้นทางรับข้อมูลยังทำงาน
จดเวลาที่ใช้กู้จริง งานที่ต้องทำด้วยมือ และช่วงข้อมูลระหว่างจุดตัดสำรองกับเวลาขัดข้องสมมติ แล้วเทียบกับระยะหยุดระบบและการสูญเสียข้อมูลที่ทีมยอมรับได้ หาก trace เดิมเปิดไม่ครบ ให้แก้ขั้นตอนสำรองหรือจุดตัดของรอบนั้นก่อนเปิดระบบให้ทีมใช้งานจริง ไฟล์สำรองที่มีชื่อครบทุกส่วนยังไม่ใช่ผลทดสอบ restore
เมื่อใดควรย้ายจาก Compose
Compose เหมาะเมื่อ VM เดียวยังรองรับงานได้ และทีมยอมรับช่วงหยุดเพื่ออัปเกรด ดูแลเครื่อง หรือกู้ข้อมูล หากต้องรับ trace ต่อเมื่อ VM เสีย ต้องขยายบริการข้ามหลายเครื่อง หรือผลซ้อมกู้คืนใช้เวลานานกว่าข้อกำหนด ให้ประเมิน Kubernetes และ datastore แบบจัดการแยกส่วนพร้อมแผนย้ายข้อมูล เกณฑ์ตัดสินควรมาจากปริมาณงานและเวลาที่กู้ได้จริง เพราะการเปลี่ยนตัวรันแอปไม่ได้ย้ายประวัติ trace หรือสร้างชุดสำรองให้เอง
อ่านเพิ่มเติม:
บทความที่เกี่ยวข้อง


Langfuse หรือ LangSmith: ทีม 5 คนอาจจ่ายต่างตั้งแต่ค่าเก้าอี้

Docker หรือ DigitalOcean: sandbox สำหรับ AI agent คิดเงินคนละจังหวะ

GitHub Actions หรือ CircleCI: งาน Docker 40 นาทีอาจเหลือ 18 นาที

ตามรอย AI agent ด้วย OpenTelemetry: อย่าเก็บพรอมป์ลับลง trace ทั้งก้อน

Sentry หรือ Datadog: ตามบั๊กในโค้ดกับเฝ้าทั้งระบบไม่ใช่งานเดียวกัน
สมัครรับจดหมายข่าวของเรา
รับข่าวสารล่าสุดเกี่ยวกับ Web3, AI และคริปโตส่งตรงถึงกล่องจดหมายของคุณ