รวมคำสั่ง Docker Compose ที่ใช้จริงบนเซิร์ฟเวอร์
สรุปคำสั่ง Docker Compose V2 ที่จำเป็นสำหรับการจัดการคอนเทนเนอร์บนเซิร์ฟเวอร์ ตั้งแต่การรัน lifecycle การดู logs ไปจนถึงการจัดการ network และ volume อย่างปลอดภัยและถูกต้องตามหลักการ
คำสั่ง Compose ที่คุณต้องใช้งานจริง
Docker Compose มีคำสั่งย่อยมากกว่า 40 คำสั่ง แต่การทำงานบนเซิร์ฟเวอร์ในแต่ละวันใช้เพียงประมาณ 12 คำสั่งเท่านั้น หน้านี้จะจัดกลุ่มคำสั่งเหล่านั้นตามงานที่คุณทำ พร้อมระบุเหตุผลสั้นๆ สำหรับแต่ละคำสั่ง และชี้ไปยังเนื้อหาเชิงลึกในกรณีที่คำสั่งนั้นอาจมีข้อควรระวังแฝงอยู่
เนื้อหาทั้งหมดในที่นี้ใช้ Compose V2 คือ docker compose โดยเว้นวรรค ไม่ใช่สคริปต์ docker-compose แบบเก่า V2 เป็น Go plugin ที่ติดตั้งมาพร้อมกับ Docker Engine และ V1 ได้ถูกถอดออกจากแพ็กเกจปัจจุบันแล้ว ดังนั้นการใช้ docker-compose: command not found บนเครื่อง Ubuntu ใหม่ ณ เดือนกรกฎาคม 2026 จึงเป็นเรื่องปกติ ไม่ใช่ข้อผิดพลาด ตรวจสอบด้วย docker compose version หากคำสั่งดังกล่าวไม่แสดงผลลัพธ์ใดๆ ให้ติดตั้งแพ็กเกจ docker-compose-plugin
ทุกคำสั่งด้านล่างนี้ต้องรันจากไดเรกทอรีที่เก็บไฟล์ compose.yaml ของคุณ เนื่องจาก Compose จะดึงชื่อโปรเจกต์จากไดเรกทอรีนั้นและค้นหาไฟล์โดยอ้างอิงจากตำแหน่งดังกล่าว หากคุณรันคำสั่งเดิมจากไดเรกทอรีที่อยู่สูงขึ้นไปหนึ่งระดับ Compose จะหยุดทำงานพร้อมกับแจ้ง no configuration file provided: not found หากรูปแบบไฟล์ยังเป็นเรื่องใหม่สำหรับคุณ ให้เริ่มต้นที่ การสร้างไฟล์ Compose ไฟล์แรกบน VPS แล้วค่อยกลับมาที่นี่เพื่อดูคำสั่งต่างๆ
วงจรชีวิต: สี่คำสั่งที่คุณต้องใช้ และหนึ่งคำสั่งสำหรับลบ container
docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose downup -d ทำหน้าที่สร้าง network, สร้าง container, สั่งเริ่มทำงาน และจบการทำงานทันที คำสั่งนี้จะคืนค่ากลับทันทีที่ container ถูก สร้าง เสร็จสิ้น ซึ่งเป็นเหตุผลว่าทำไมสคริปต์ deploy ที่ใช้ curl ตรวจสอบต่อท้ายมักจะล้มเหลวในการรันครั้งแรก up -d --wait จะรอจนกว่าทุก service ที่ประกาศ healthcheck ไว้จะรายงานสถานะว่าปกติ และจะคืนค่าสถานะเป็น non-zero หากมี service ใดไม่สามารถเข้าสู่สถานะปกติได้ คำสั่งนี้จะมีประสิทธิภาพเท่ากับตัวตรวจสอบที่กำหนดไว้เท่านั้น ดังนั้นควรเขียน healthcheck ที่ Compose เชื่อถือได้ ก่อนที่จะนำไปใช้ในระบบอัตโนมัติ
stop จะหยุดการทำงานของ container แต่ยังคงเก็บ container เหล่านั้นไว้ ทำให้ start สามารถนำ container เดิมกลับมาใช้งานต่อได้โดยที่ข้อมูลใน writable layer ยังคงอยู่ ส่วน down จะหยุดการทำงานแล้วลบ container รวมถึง network ของโปรเจกต์ทิ้ง ข้อมูลใดก็ตามที่เขียนไว้ภายใน container แต่ไม่ได้อยู่ใน volume จะถูกลบหายไปทั้งหมด นี่คือความเข้าใจผิดที่สร้างความเสียหายมากที่สุดในการใช้งาน Compose และ ความแตกต่างทั้งหมดระหว่าง down และ stop ได้อธิบายถึงผลกระทบที่อาจเกิดขึ้นไว้แล้ว
restart ไม่ใช่การ reload คำสั่งนี้จะหยุดและเริ่ม container เดิมด้วยการตั้งค่าที่มีอยู่แล้ว ดังนั้นการเปลี่ยนแปลง environment variable, การเปลี่ยน image tag หรือการแก้ไข port mapping จะไม่มีผลใดๆ ทั้งสิ้น หากต้องการนำการเปลี่ยนแปลงไฟล์ไปใช้ คุณต้องรัน up -d อีกครั้ง Compose จะเปรียบเทียบแต่ละ service กับ container ที่กำลังทำงานอยู่ และจะสร้างใหม่เฉพาะ service ที่มีการตั้งค่าเปลี่ยนแปลงไปเท่านั้น
การนำการเปลี่ยนแปลงไปใช้: การสร้างใหม่ (recreate), การดึงข้อมูล (pull) หรือการสร้างอิมเมจใหม่ (rebuild)
docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build webup -d เพียงอย่างเดียวจะไม่ส่งผลใดๆ หากไม่มีการเปลี่ยนแปลงใดเกิดขึ้น ซึ่งเป็นเหตุผลว่าทำไมจึงปลอดภัยที่จะเรียกใช้ซ้ำๆ --force-recreate จะข้ามการเปรียบเทียบนั้นและแทนที่คอนเทนเนอร์ทุกตัวแม้ว่าการกำหนดค่าจะเหมือนเดิมทุกประการ ดังนั้นจึงเป็นวิธีที่เร็วที่สุดในการล้างสถานะที่ผิดปกติภายในคอนเทนเนอร์
การอัปเดตอิมเมจต้องใช้สองคำสั่งเนื่องจากทั้งสองคำสั่งทำหน้าที่ต่างกัน pull จะดาวน์โหลดอิมเมจปัจจุบันสำหรับแต่ละแท็กที่ระบุไว้ในไฟล์ จากนั้น up -d จะตรวจสอบพบว่า ID ของอิมเมจของบริการไม่ตรงกับคอนเทนเนอร์ที่กำลังทำงานอยู่และจะสร้างขึ้นใหม่ หากข้ามขั้นตอนการ pull ไป up -d จะยังคงรัน latest ของเดือนที่แล้วต่อไปโดยไม่มีข้อผิดพลาด
build ใช้กับบริการที่ประกาศส่วน build: แทนที่จะเป็น image: โดย up -d --build จะทำการ build และ start ในขั้นตอนเดียว ซึ่งเป็นวงจรการทำงานปกติในขณะที่คุณกำลังแก้ไขโค้ด ให้ใช้ --no-cache ก็ต่อเมื่อเลเยอร์ที่ถูกแคชไว้ล้าสมัยอย่างชัดเจนเท่านั้น เนื่องจากคำสั่งนี้จะสร้างทุกเลเยอร์ขึ้นใหม่ตั้งแต่ต้น
การตรวจสอบสิ่งที่กำลังทำงานอยู่
docker compose ps
docker compose ps -a
docker compose logs -f --tail=100
docker compose logs --since 15m --timestamps db
docker compose top
docker compose lsps จะแสดงเฉพาะคอนเทนเนอร์ที่กำลังทำงานอยู่เท่านั้น บริการที่ขัดข้องระหว่างการเริ่มทำงานจะไม่ปรากฏให้เห็นจนกว่าคุณจะเพิ่ม -a ดังนั้นการที่คอนเทนเนอร์หายไปจาก ps ในขณะที่ ps -a แสดงสถานะเป็น Exited (1) จึงเป็นลักษณะปกติของความล้มเหลวในการเริ่มทำงาน ให้ตรวจสอบ exit code แล้วจึงอ่าน log
logs -f จะติดตามทุกบริการพร้อมกันและใส่ชื่อบริการไว้หน้าแต่ละบรรทัด ซึ่งเป็นมุมมองที่คุณต้องการเมื่อบริการต่างๆ สื่อสารกันและลำดับของเหตุการณ์มีความสำคัญ ให้ระบุชื่อบริการเพื่อจำกัดขอบเขตการแสดงผล --tail=100 มีความสำคัญสำหรับคอนเทนเนอร์ที่ทำงานมานานเป็นเดือน เพราะค่าเริ่มต้นจะพิมพ์ประวัติทั้งหมดออกมาจนเต็มหน้าจอเทอร์มินัล --since 15m จะตอบคำถามที่คุณมักจะมี ซึ่งก็คือเกิดอะไรขึ้นในช่วงการรีสตาร์ทที่คุณเพิ่งทำไป
top จะแสดงรายการกระบวนการ (process) ภายในแต่ละคอนเทนเนอร์ ซึ่งช่วยแยกแยะระหว่าง "คอนเทนเนอร์กำลังทำงาน" กับ "กระบวนการภายในคอนเทนเนอร์กำลังทำงาน" ออกจากกัน ls จะออกจากไดเรกทอรีปัจจุบันและแสดงรายการโปรเจกต์ Compose ทั้งหมดบนโฮสต์พร้อมสถานะ เพื่อให้คุณสามารถค้นหาสแต็กที่คุณเริ่มทำงานไว้เมื่อสามเดือนก่อนได้
การเข้าถึงเชลล์ภายในเซอร์วิส
docker compose exec web sh
docker compose exec -u root web sh
docker compose run --rm web env
docker compose run --rm --no-deps web shexec ใช้สำหรับรันคำสั่งภายในคอนเทนเนอร์ที่กำลังทำงานอยู่ ส่วน run ใช้สำหรับเริ่มคอนเทนเนอร์ใหม่จากนิยามเซอร์วิสเดิม ซึ่งจำเป็นในกรณีที่เซอร์วิสไม่สามารถทำงานค้างไว้นานพอที่จะใช้คำสั่ง exec เข้าไปได้ ควรใช้ run คู่กับ --rm เสมอ เพราะหากไม่มีแฟล็กนี้ ทุกครั้งที่เรียกใช้จะทิ้งคอนเทนเนอร์ที่หยุดทำงานไว้เบื้องหลัง และคอนเทนเนอร์เหล่านี้จะสะสมจนทำให้ docker compose ps -a อ่านค่าไม่ได้
ให้ลองใช้ sh ก่อน bash เนื่องจากอิมเมจที่ใช้ Alpine จะไม่มี bash ติดตั้งมาให้ และจะแสดงข้อความแจ้งเตือนว่า exec: "bash": executable file not found in $PATH การเพิ่ม --no-deps เข้าไปใน run จะช่วยข้ามการตรวจสอบ dependency ของเซอร์วิส ซึ่งช่วยป้องกันไม่ให้การตรวจสอบการตั้งค่าเพียงชั่วคราวไปสั่งเริ่มการทำงานของฐานข้อมูลทั้งหมดของคุณ
run --rm web env เป็นวิธีที่เร็วที่สุดในการดูสภาพแวดล้อม (environment) ที่เซอร์วิสได้รับจริง หลังจากที่ไฟล์ .env, บล็อก environment: และตัวแปรเชลล์ทั้งหมดถูกรวมเข้าด้วยกันแล้ว หากค่าที่ได้ไม่ถูกต้อง สาเหตุส่วนใหญ่มักเกิดจากลำดับการรวมค่า และ วิธีการที่ Compose จัดการกับไฟล์ env และ secrets จะอธิบายว่าแหล่งข้อมูลใดมีลำดับความสำคัญสูงสุด
เครือข่าย พอร์ต และการแก้ไขชื่อโฮสต์
docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networksCompose จะนำทุกบริการไปไว้บนเครือข่ายโปรเจกต์เดียวกัน และชื่อของแต่ละบริการจะกลายเป็นชื่อ DNS ภายในเครือข่ายนั้น การรัน getent hosts db ภายใน web จะแสดง IP ของคอนเทนเนอร์หากการแก้ไขชื่อสำเร็จ และจะไม่แสดงผลใดๆ หากล้มเหลว วิธีนี้จึงช่วยตอบคำถามว่า "คอนเทนเนอร์เหล่านี้มองเห็นกันหรือไม่" ได้ภายในเวลาเพียงสองวินาที หากชื่อโฮสต์แก้ไขได้แต่การเชื่อมต่อถูกปฏิเสธ แสดงว่ากระบวนการภายใน db กำลังผูกอยู่กับ 127.0.0.1 แทนที่จะเป็น 0.0.0.0 ทำให้ไม่สามารถรับแพ็กเก็ตจากคอนเทนเนอร์อื่นได้ รายละเอียดเพิ่มเติมของโมเดลนี้อยู่ใน วิธีการทำงานของเครือข่ายและ DNS ใน Compose
port web 80 จะแสดงที่อยู่โฮสต์และพอร์ตที่พอร์ตของคอนเทนเนอร์ถูกเผยแพร่ออกไป ซึ่งช่วยลดการคาดเดาเมื่อการแมปพอร์ตมาจากตัวแปร การเผยแพร่พอร์ตยังเป็นการเขียนกฎไฟร์วอลล์ที่ Docker จัดการเอง ซึ่งกฎนี้จะอยู่ก่อนหน้ากฎที่คุณตั้งไว้ ส่งผลให้บริการที่คุณเข้าใจว่าเป็นส่วนตัวอาจเปิดเผยต่ออินเทอร์เน็ตได้ กรณีนี้อธิบายไว้ใน เหตุใดพอร์ต Docker ที่เผยแพร่จึงข้ามการทำงานของ ufw
Volumes และข้อมูล
docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -vconfig --volumes จะแสดงรายการ named volumes ที่โปรเจกต์ประกาศไว้ โดยแสดงผลทีละบรรทัด รายการนี้คือสิ่งที่คุณต้องสำรองข้อมูล cp ใช้สำหรับคัดลอกไฟล์เข้าหรือออกจาก container โดยไม่ต้องเปิด shell ผ่านการใช้รูปแบบ service:path ในฝั่งที่เป็น container
down -v จะลบ named volumes เหล่านั้นทิ้งไปพร้อมกับ container นี่เป็นคำสั่งที่เหมาะสมสำหรับการรื้อถอน stack ที่ใช้ทดสอบ แต่เป็นคำสั่งที่ผิดพลาดหากใช้กับข้อมูลที่คุณต้องการเก็บรักษา เนื่องจากไม่มีการยืนยันและไม่สามารถย้อนกลับได้ ในขณะที่ bind mounts จะยังคงอยู่เนื่องจากไฟล์เหล่านี้ถูกเก็บไว้บน filesystem ของ host ความแตกต่างในขอบเขตความเสียหายนี้เป็นเหตุผลหนึ่งที่ควรเลือกอย่างรอบคอบระหว่าง bind mounts และ named volumes
การล้างข้อมูลเพื่อเพิ่มพื้นที่ดิสก์โดยไม่สูญเสียข้อมูล
docker compose down --remove-orphans
docker system df
docker image prune -a
docker builder prune--remove-orphans จะลบ container ที่อยู่ในโปรเจกต์แต่ไม่มีระบุไว้ในไฟล์แล้ว ซึ่งเป็นสิ่งที่เกิดขึ้นหลังจากเปลี่ยนชื่อ service หากไม่ใช้คำสั่งนี้ container เหล่านั้นจะยังคงทำงานอยู่โดยที่ docker compose ps มองไม่เห็น
docker system df จะแสดงให้เห็นว่าพื้นที่ดิสก์ถูกใช้ไปกับส่วนใดบ้างก่อนที่คุณจะลบข้อมูล โดยจะแยกรายละเอียดของ image, container, local volume และ build cache พร้อมระบุจำนวนพื้นที่ที่สามารถเรียกคืนได้สำหรับแต่ละรายการ image prune -a จะลบ image ทุกตัวที่ไม่มี tag ใดอ้างอิงถึง ซึ่งบนเซิร์ฟเวอร์ที่มีการดึง image ขนาดใหญ่หลายเวอร์ชัน คำสั่งนี้มักจะช่วยคืนพื้นที่ได้มากที่สุด builder prune จะล้าง build cache ซึ่งจะเพิ่มขนาดขึ้นเรื่อยๆ บนเซิร์ฟเวอร์ที่มีการ build image เอง
คำสั่งทั้งหมดข้างต้นจะไม่ส่งผลกระทบต่อ named volume โดยจะมีเพียง docker volume prune และ docker compose down -v เท่านั้นที่จัดการกับส่วนนี้
การตรวจสอบไฟล์ก่อนเกิดข้อผิดพลาด
docker compose config --quiet
docker compose config --services
docker compose --dry-run up -dconfig --quiet จะทำการตรวจสอบความถูกต้องและไม่แสดงผลลัพธ์ใดๆ หากการตรวจสอบสำเร็จ จึงเหมาะสำหรับขั้นตอนก่อนการ deploy หรือใช้ใน git hook ส่วน config จะแสดงเนื้อหาไฟล์ที่รวมและแทนที่ตัวแปรทั้งหมดแล้ว ซึ่งช่วยให้คุณยืนยันได้ว่าตัวแปรถูกแทนที่ด้วยค่าที่ถูกต้องและไฟล์ override ถูกนำมาใช้งานตามลำดับที่คาดหวัง หากมีตัวแปรที่ไม่ได้กำหนดค่าไว้ จะแสดงเป็นค่าว่างพร้อมกับคำเตือน The "X" variable is not set. Defaulting to a blank string.
--dry-run เป็น global flag ไม่ใช่ subcommand flag จึงต้องวางไว้หน้า up คำสั่งนี้จะแสดงทุกการกระทำที่ Docker Compose จะดำเนินการโดยไม่มีการเปลี่ยนแปลงใดๆ เกิดขึ้นจริง ซึ่งเป็นการใช้เวลา 30 วินาทีที่คุ้มค่าก่อนการรัน down บน stack ที่มีความสำคัญ
การทำงานข้ามไฟล์ โปรไฟล์ และโปรเจกต์
docker compose -f compose.yaml -f compose.prod.yaml up -d
docker compose --profile debug up -d
docker compose -p staging up -dการใช้ flag -f หลายรายการจะถูกรวมเข้าด้วยกันตามลำดับ โดยไฟล์ที่ระบุทีหลังจะเขียนทับค่าเดิมในไฟล์ก่อนหน้าแบบคีย์ต่อคีย์ นี่เป็นวิธีมาตรฐานในการเก็บไฟล์ฐานไว้หนึ่งไฟล์และใช้ไฟล์ override สำหรับ production ขนาดเล็ก อย่างไรก็ตาม กฎการรวมข้อมูลสำหรับรายการ (list) และแผนผัง (map) จะแตกต่างกัน โปรดอ่าน วิธีการที่ Compose รวมไฟล์หลายไฟล์เข้าด้วยกัน ก่อนที่คุณจะเริ่มแก้ไขปัญหาที่ไม่คาดคิด
--profile จะเริ่มบริการที่ถูกแท็กด้วยโปรไฟล์นั้นควบคู่ไปกับบริการที่ไม่ได้แท็ก ซึ่งช่วยแยกเครื่องมือสำหรับ debug ออกจากการทำงานปกติของ up ส่วน -p ใช้สำหรับกำหนดชื่อโปรเจกต์ เพื่อให้สามารถรัน stack เดียวกันสองชุดควบคู่กันได้โดยใช้เครือข่ายและชื่อ volume ที่แยกจากกัน การทำให้ stack กลับมาทำงานหลังการรีบูตไม่ใช่คำสั่งที่คุณต้องพิมพ์เอง แต่เป็น unit ที่ทำงานให้คุณโดยอัตโนมัติ ซึ่งอธิบายไว้ใน การเริ่ม Compose stack ตอนบูตเครื่อง
FAQ
อะไรมาแทนที่ docker-compose ที่มีเครื่องหมายยัติภังค์?
Compose V2 ซึ่งเรียกใช้งานด้วย docker compose โดยเว้นวรรค มันเป็นปลั๊กอินที่รวมมากับ Docker Engine และเครื่องมือภาษา Python เวอร์ชัน V1 จะไม่ถูกติดตั้งมากับแพ็กเกจปัจจุบันอีกต่อไป หากการเรียกใช้งานแบบเว้นวรรคไม่แสดงผลลัพธ์ใดๆ ให้ติดตั้งแพ็กเกจ docker-compose-plugin สำหรับดิสทริบิวชันของคุณ ให้อัปเดตสคริปต์เก่าให้เป็นรูปแบบเว้นวรรคแทนการสร้าง alias เนื่องจาก V2 มีแฟล็กที่ V1 ไม่มี
ทำไม docker compose restart ถึงไม่รับการเปลี่ยนแปลงค่าคอนฟิกของฉัน?
restart จะหยุดและเริ่มคอนเทนเนอร์เดิมด้วยการตั้งค่าที่ถูกสร้างขึ้นมาตั้งแต่แรก และมันจะไม่โหลด compose.yaml ซ้ำ การเปลี่ยนแปลงใดๆ ต่อ environment variable, พอร์ต, volume หรือ image tag จำเป็นต้องใช้ docker compose up -d ซึ่งจะเปรียบเทียบแต่ละเซอร์วิสกับคอนเทนเนอร์ที่กำลังทำงานอยู่และสร้างใหม่เฉพาะส่วนที่แตกต่างกัน ให้เพิ่ม --force-recreate เมื่อคุณต้องการให้เกิดการแทนที่แม้ว่าจะไม่มีสิ่งใดในไฟล์เปลี่ยนแปลงก็ตาม
ฉันจะอัปเดตเซอร์วิสให้เป็น image เวอร์ชันใหม่ได้อย่างไร?
ให้รัน docker compose pull แล้วตามด้วย docker compose up -d คำสั่ง pull จะดึง image ปัจจุบันสำหรับแต่ละ tag ในไฟล์ และ up -d จะสร้างเซอร์วิสใหม่หาก image ID ไม่ตรงกับคอนเทนเนอร์ที่รันอยู่ การรัน up -d เพียงอย่างเดียวจะเป็นการใช้ image ที่อยู่ในดิสก์เดิม ซึ่งเป็นเหตุผลว่าทำไม stack ที่ล็อกไว้ที่ latest จึงยังคงใช้ build ที่เก่าหลายเดือนโดยไม่แสดงข้อผิดพลาดใดๆ
คำสั่งล้างข้อมูลใดบ้างที่ปลอดภัยบนเซิร์ฟเวอร์ที่กำลังทำงานอยู่?
docker system df, docker image prune -a และ docker builder prune จะลบเฉพาะ image และแคชเท่านั้น ดังนั้นเซอร์วิสที่กำลังทำงานอยู่จะยังคงทำงานต่อไปและ named volume จะไม่ได้รับผลกระทบ คู่คำสั่งที่อันตรายคือ docker compose down -v และ docker volume prune ซึ่งจะลบ named volume โดยไม่มีการแจ้งเตือน ให้รัน docker compose config --volumes ก่อนเพื่อให้คุณทราบว่ามีข้อมูลใดบ้างที่เสี่ยงต่อการถูกลบ
ฉันสามารถรันคำสั่งเดียวโดยไม่เริ่มทั้ง stack ได้หรือไม่?
ได้ docker compose run --rm --no-deps web sh จะเริ่มคอนเทนเนอร์เดี่ยวจากนิยามเซอร์วิส web โดยข้าม dependency ของมัน และจะลบคอนเทนเนอร์ทิ้งเมื่อคุณออกจากโปรแกรม ให้ใช้ exec แทนเมื่อคอนเทนเนอร์กำลังทำงานอยู่ เพราะ exec จะเชื่อมต่อเข้ากับโพรเซสที่กำลังทำงานอยู่และแสดงสถานะจริงที่เซอร์วิสนั้นเป็นอยู่