Docker Compose: รวมคำสั่งใช้งานจริงบนเซิร์ฟเวอร์
รวมคำสั่ง Docker Compose V2 ที่ใช้ประจำบนเซิร์ฟเวอร์ แยกตามงานทั้งเริ่มระบบ ใช้การเปลี่ยนแปลง ดู logs เข้า shell จัดการ network และ volumes พร้อม cleanup อย่างปลอดภัย
คำสั่ง Compose ที่คุณใช้งานจริง
Docker Compose มีคำสั่งย่อยมากกว่า 40 คำสั่ง งานประจำวันบนเซิร์ฟเวอร์ใช้ประมาณ 12 คำสั่ง หน้านี้จัดกลุ่มคำสั่งเหล่านั้นตามงานที่คุณกำลังทำ อธิบายเหตุผลโดยสรุปสำหรับแต่ละคำสั่ง และชี้ไปยังเนื้อหาเชิงลึกเมื่อคำสั่งนั้นมีข้อควรระวังที่อาจทำให้เกิดปัญหา
เนื้อหาทั้งหมดนี้ใช้ Compose V2: docker compose โดยเว้นวรรค ไม่ใช่สคริปต์ docker-compose รุ่นเก่า V2 เป็นปลั๊กอิน Go ที่ติดตั้งพร้อม Docker Engine และ V1 ไม่มีอยู่ในแพ็กเกจปัจจุบันแล้ว ดังนั้นการพบ docker-compose: command not found บนเครื่อง Ubuntu ใหม่ ณ เดือนกรกฎาคม 2026 จึงเป็นพฤติกรรมที่คาดไว้ ไม่ใช่ข้อผิดพลาด ตรวจสอบด้วย docker compose version หากคำสั่งดังกล่าวไม่แสดงผลใด ให้ติดตั้งแพ็กเกจ docker-compose-plugin
คำสั่งด้านล่างทั้งหมดต้องเรียกใช้จากไดเรกทอรีที่มี compose.yaml อยู่ เนื่องจาก Compose ใช้ชื่อโปรเจกต์จากไดเรกทอรีนั้น และค้นหาไฟล์โดยอ้างอิงจากไดเรกทอรีดังกล่าว หากเรียกใช้คำสั่งเดียวกันจากไดเรกทอรีที่อยู่สูงขึ้นไป 1 ระดับ Compose จะหยุดทำงานพร้อม no configuration file provided: not found หากรูปแบบไฟล์ยังเป็นเรื่องใหม่สำหรับคุณ ให้เริ่มจาก ไฟล์ Compose ไฟล์แรกบน VPS แล้วกลับมาที่หน้านี้เพื่อดูคำสั่งต่าง ๆ
วงจรการทำงาน: 4 คำสั่งที่คุณใช้ และ 1 คำสั่งที่ลบคอนเทนเนอร์
docker compose up -d
docker compose up -d --wait
docker compose stop
docker compose start
docker compose restart web
docker compose downup -d สร้าง network สร้าง containers เริ่มการทำงาน และคืนการควบคุมทันที โดยจะคืนการควบคุมเมื่อ containers ถูก สร้าง แล้วเท่านั้น ดังนั้นสคริปต์ deploy ที่เรียกใช้ curl probe ต่อจากคำสั่งนี้จึงมักล้มเหลวในการลองครั้งแรก up -d --wait จะรอจนกว่า service ทุกตัวที่ประกาศ healthcheck จะรายงานสถานะ healthy และจะจบการทำงานด้วยค่า non-zero หากมี service ใดไม่ผ่านสถานะดังกล่าวในท้ายที่สุด ความถูกต้องของ flag นี้ขึ้นอยู่กับ healthcheck ที่อยู่เบื้องหลัง ดังนั้นควรเขียน healthcheck ที่ Compose เชื่อถือได้ ก่อนนำไปใช้ใน automation
stop หยุดการทำงานของ containers แต่ยังคงเก็บไว้ ดังนั้น start จึงนำ containers เดิมกลับมาใช้งานต่อ พร้อม writable layer เดิม down หยุด containers แล้วลบ containers และ project network ข้อมูลใดก็ตามที่เขียนไว้ภายใน container และไม่ได้อยู่ใน volume จะถูกลบไปพร้อมกัน นี่คือความเข้าใจผิดเกี่ยวกับ Compose ที่สร้างความเสียหายมากที่สุด และ ความแตกต่างทั้งหมดระหว่าง down กับ stop อธิบายจุดที่ปัญหานี้ส่งผลกระทบ
restart ไม่ใช่การ reload คำสั่งนี้จะหยุดและเริ่ม container เดิม โดยใช้ configuration ที่มีอยู่แล้ว ดังนั้นการเปลี่ยน environment variable, image tag ใหม่ หรือ port mapping ที่แก้ไขจะไม่มีผลใดๆ หากต้องการใช้การเปลี่ยนแปลงในไฟล์ ให้เรียกใช้ up -d อีกครั้ง Compose จะเปรียบเทียบ service แต่ละตัวกับ container ที่กำลังทำงาน และจะสร้างใหม่เฉพาะ service ที่ configuration เปลี่ยนแปลงเท่านั้น
การใช้การเปลี่ยนแปลง: สร้างใหม่ ดึงอิมเมจ หรือบิลด์ใหม่
docker compose up -d --force-recreate
docker compose pull && docker compose up -d
docker compose build --no-cache web
docker compose up -d --build webการเรียกใช้ up -d เพียงอย่างเดียวจะไม่ทำอะไรเมื่อไม่มีการเปลี่ยนแปลง ซึ่งทำให้สามารถเรียกใช้ซ้ำได้อย่างปลอดภัย --force-recreate จะบังคับให้แทนที่ทุกคอนเทนเนอร์ แม้ว่าการกำหนดค่าจะเหมือนเดิม จึงเป็นวิธีที่รวดเร็วที่สุดในการล้างสถานะผิดปกติภายในคอนเทนเนอร์
การอัปเดตอิมเมจต้องใช้ 2 คำสั่ง เนื่องจากแต่ละคำสั่งทำหน้าที่ต่างกัน pull จะดาวน์โหลดอิมเมจล่าสุดสำหรับแต่ละแท็กที่ระบุไว้ในไฟล์ จากนั้น up -d จะตรวจพบว่า image ID ของ service ไม่ตรงกับคอนเทนเนอร์ที่กำลังทำงานอยู่ และจะสร้างคอนเทนเนอร์นั้นใหม่ หากข้ามขั้นตอน pull up -d จะยังคงให้ latest ของเดือนที่แล้วทำงานต่อไปโดยไม่แสดงข้อผิดพลาด
build ใช้กับ service ที่ประกาศส่วน build: แทน image: up -d --build จะบิลด์และเริ่มทำงานในขั้นตอนเดียว ซึ่งเป็นกระบวนการปกติระหว่างการแก้ไขโค้ด ให้ใช้ --no-cache เฉพาะเมื่อพบว่า layer ที่อยู่ในแคชล้าสมัยอย่างชัดเจน เนื่องจากคำสั่งนี้จะบิลด์ทุก layer ใหม่ตั้งแต่ต้น
ตรวจสอบสิ่งที่กำลังทำงาน
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) นี่คือรูปแบบปกติของความล้มเหลวระหว่างการเริ่มต้น อ่านรหัสการออก จากนั้นอ่านบันทึก
logs -f ติดตามทุกบริการพร้อมกัน และเติมชื่อบริการไว้หน้าทุกบรรทัด มุมมองนี้เหมาะเมื่อบริการต่าง ๆ ติดต่อสื่อสารกันและลำดับเหตุการณ์มีความสำคัญ ระบุชื่อบริการเพื่อจำกัดผลลัพธ์ --tail=100 มีความสำคัญกับคอนเทนเนอร์ที่ทำงานมาแล้วหนึ่งเดือน เพราะค่าเริ่มต้นจะแสดงประวัติทั้งหมดและทำให้เทอร์มินัลมีข้อมูลจำนวนมาก --since 15m ตอบคำถามที่มักต้องการทราบ นั่นคือเกิดอะไรขึ้นระหว่างการเริ่มต้นใหม่ที่เพิ่งดำเนินการ
top แสดงกระบวนการภายในคอนเทนเนอร์แต่ละรายการ ซึ่งช่วยแยกความแตกต่างระหว่าง “คอนเทนเนอร์กำลังทำงาน” กับ “กระบวนการภายในคอนเทนเนอร์กำลังทำงาน” ls ออกจากไดเรกทอรีปัจจุบันและแสดง Compose project ทั้งหมดบน host พร้อมสถานะของแต่ละรายการ คุณจึงค้นหา stack ที่เริ่มต้นไว้เมื่อสามเดือนก่อนได้
การเปิด shell ภายใน service
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 เรียกใช้คำสั่งภายใน container ที่กำลังทำงานอยู่แล้ว ส่วน run จะเริ่มต้น container ใหม่จาก service definition เดียวกัน ซึ่งจำเป็นเมื่อ service ทำงานไม่นานพอที่จะใช้ exec เข้าไปได้ ให้ใช้ run ร่วมกับ --rm เสมอ เพราะหากไม่ใช้ ทุกครั้งที่เรียกใช้จะทิ้ง container ที่หยุดทำงานไว้ และ container เหล่านี้จะสะสมจนทำให้ docker compose ps -a อ่านไม่ได้
ให้ลองใช้ sh ก่อน bash อิมเมจที่อิงกับ Alpine ไม่มี bash และจะแสดงข้อผิดพลาดเป็น exec: "bash": executable file not found in $PATH การเพิ่ม --no-deps ให้กับ run จะข้าม dependencies ของ service ทำให้การตรวจสอบ configuration อย่างรวดเร็วไม่ต้องเริ่มต้นฐานข้อมูลทั้งหมด
run --rm web env เป็นวิธีที่เร็วที่สุดในการดู environment ที่ service ได้รับจริง หลังจากรวมไฟล์ .env, บล็อก environment: และตัวแปร shell ทั้งหมดแล้ว เมื่อค่าไม่ถูกต้อง ลำดับการรวมมักเป็นสาเหตุ และ วิธีที่ Compose แก้ไขไฟล์ env และ secrets อธิบายว่าแหล่งข้อมูลใดมีลำดับความสำคัญสูงสุด
เครือข่าย พอร์ต และการแปลงชื่อ
docker compose port web 80
docker compose exec web getent hosts db
docker compose config --networksCompose จะวางทุก service ไว้ในเครือข่ายของ project เดียวกัน และชื่อของแต่ละ service จะเป็นชื่อ DNS บนเครือข่ายนั้น การเรียกใช้ getent hosts db ภายใน web จะแสดง IP ของ container เมื่อการแปลงชื่อทำงาน และจะไม่แสดงผลลัพธ์เมื่อการแปลงชื่อไม่ทำงาน จึงใช้ตอบได้ภายใน 2 วินาทีว่า "container เหล่านี้ติดต่อกันได้หรือไม่" หากแปลงชื่อได้แต่การเชื่อมต่อถูกปฏิเสธ แสดงว่า process ภายใน db bind อยู่กับ 127.0.0.1 แทนที่จะเป็น 0.0.0.0 จึงไม่รับ packet จาก container อื่น รายละเอียดส่วนที่เหลือของโมเดลนี้อยู่ใน วิธีที่ Compose จัดการเครือข่ายและ DNS ของ service
port web 80 จะแสดง address และ port บน host ที่เผยแพร่ port ของ container ไว้ ซึ่งช่วยไม่ต้องคาดเดาเมื่อ mapping มาจากตัวแปร การเผยแพร่ port ยังสร้างกฎ firewall ที่ Docker จัดการเองด้วย และกฎดังกล่าวจะอยู่ก่อนกฎของคุณ ดังนั้น service ที่คุณคิดว่าเป็น private อาจเปิดให้เข้าถึงได้จากอินเทอร์เน็ต กรณีนี้อธิบายไว้ใน เหตุใด port ของ Docker ที่เผยแพร่จึงข้าม ufw
Volumes และข้อมูล
docker compose config --volumes
docker compose cp db:/etc/postgresql/pg_hba.conf ./pg_hba.conf
docker compose down -vconfig --volumes แสดง volumes ที่มีชื่อซึ่งโปรเจกต์ประกาศไว้ โดยแสดงรายการละ 1 บรรทัด รายการดังกล่าวคือสิ่งที่ต้องสำรองข้อมูล cp ใช้คัดลอกไฟล์เข้าหรือออกจาก container โดยไม่ต้องเปิด shell โดยใช้รูปแบบ service:path ทางฝั่งใดก็ตามที่เป็น container
down -v ลบ volumes ที่มีชื่อเหล่านั้นพร้อมกับ containers คำสั่งนี้เหมาะสำหรับลบ test 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 จะลบคอนเทนเนอร์ที่เป็นของโปรเจกต์ แต่ไม่ปรากฏอยู่ในไฟล์แล้ว ซึ่งเป็นผลลัพธ์ที่เกิดขึ้นเมื่อเปลี่ยนชื่อ service หากไม่ใช้คำสั่งนี้ คอนเทนเนอร์เหล่านั้นจะยังคงทำงานอยู่และมองไม่เห็นใน docker compose ps
docker system df แสดงว่าพื้นที่ดิสก์ถูกใช้ไปกับสิ่งใดก่อนที่คุณจะลบข้อมูล โดยแยก images, containers, local volumes และ build cache พร้อมแสดงพื้นที่ที่เรียกคืนได้ของแต่ละรายการ image prune -a จะลบทุก image ที่ไม่มี tag ใดอ้างถึง และบนเครื่องที่ดึง image ขนาดใหญ่มาหลายเวอร์ชัน การลบนี้มักคืนพื้นที่ได้มากที่สุด builder prune จะล้าง build cache ซึ่งจะเพิ่มขึ้นอย่างเงียบ ๆ บนเซิร์ฟเวอร์ที่ใช้สร้าง images ของตนเอง
คำสั่งเหล่านี้ไม่มีคำสั่งใดแตะต้อง 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 ไม่ใช่ flag ของ subcommand จึงต้องวางไว้ก่อน up คำสั่งนี้จะแสดงการดำเนินการทั้งหมดที่ 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-f หลายรายการจะถูกรวมตามลำดับ และไฟล์ที่อยู่หลังสุดจะแทนที่ค่าของไฟล์ก่อนหน้าเป็นรายคีย์ วิธีนี้เป็นมาตรฐานสำหรับการมีไฟล์พื้นฐาน 1 ไฟล์และไฟล์ override ขนาดเล็กสำหรับ production แต่กฎจะแตกต่างกันสำหรับรายการและแมป ดังนั้นโปรดอ่าน วิธีที่ Compose รวมไฟล์หลายไฟล์ ก่อนตรวจสอบปัญหาที่ไม่คาดคิด
--profile จะเริ่มบริการที่ติดแท็กด้วยโปรไฟล์นั้นพร้อมกับบริการที่ไม่มีแท็ก ซึ่งช่วยไม่ให้เครื่องมือดีบักอยู่ใน up ปกติ -p จะกำหนดชื่อโปรเจกต์ ทำให้สามารถเรียกใช้ stack เดียวกัน 2 ชุดพร้อมกันได้ โดยใช้ network และชื่อ volume แยกกัน การทำให้ stack กลับมาทำงานหลัง reboot ไม่ใช่คำสั่งที่คุณต้องพิมพ์เอง แต่เป็น unit ที่ทำงานแทนคุณ โดยอธิบายไว้ใน การเริ่ม Compose stack เมื่อบูตระบบ
FAQ
อะไรมาแทนที่ docker-compose ซึ่งใช้เครื่องหมายยัติภังค์?
Compose V2 เรียกใช้ด้วย docker compose โดยเว้นวรรคระหว่างคำ ซึ่งเป็นปลั๊กอินที่รวมมากับ Docker Engine และแพ็กเกจปัจจุบันจะไม่ติดตั้งเครื่องมือ Python V1 อีกต่อไป หากรูปแบบที่เว้นวรรคไม่แสดงผล ให้ติดตั้งแพ็กเกจ docker-compose-plugin สำหรับดิสทริบิวชันของคุณ ควรแก้ไขสคริปต์เดิมให้ใช้รูปแบบที่เว้นวรรค แทนการเพิ่ม alias เนื่องจาก V2 มี flags ที่ V1 ไม่มี
เหตุใด docker compose restart จึงไม่รับการเปลี่ยนแปลงในไฟล์กำหนดค่าของฉัน?
restart จะหยุดและเริ่ม container เดิมใหม่ โดยใช้การกำหนดค่าที่ใช้สร้าง container นั้น และจะไม่อ่าน compose.yaml ใหม่ การเปลี่ยนแปลงตัวแปรสภาพแวดล้อม ports volumes หรือ image tag ต้องใช้ docker compose up -d ซึ่งจะเปรียบเทียบแต่ละ service กับ container ที่กำลังทำงานอยู่ และสร้าง service ที่แตกต่างกันขึ้นใหม่ เพิ่ม --force-recreate เมื่อต้องการให้แทนที่ container แม้ไม่มีการเปลี่ยนแปลงใดในไฟล์
ฉันจะอัปเดต service ให้ใช้ image รุ่นใหม่กว่าได้อย่างไร?
เรียกใช้ docker compose pull แล้วตามด้วย docker compose up -d คำสั่ง pull จะดึง image ปัจจุบันสำหรับแต่ละ tag ในไฟล์ และ up -d จะสร้าง service ที่ image ID ไม่ตรงกับ container ขึ้นใหม่ การเรียกใช้ up -d เพียงอย่างเดียวจะนำ image ที่มีอยู่ในดิสก์กลับมาใช้ ซึ่งเป็นสาเหตุที่ stack ที่ระบุเป็น latest ยังคงใช้ build ที่มีอายุหลายเดือนโดยไม่แสดงข้อผิดพลาด
คำสั่ง cleanup ใดปลอดภัยสำหรับเซิร์ฟเวอร์ที่กำลังทำงาน?
docker system df, docker image prune -a และ docker builder prune จะลบเฉพาะ images และ cache ดังนั้น service ที่กำลังทำงานจะยังใช้งานได้ และ named volumes จะไม่ถูกแก้ไข คู่คำสั่งที่อันตรายคือ docker compose down -v และ docker volume prune ซึ่งจะลบ named volumes โดยไม่ถามยืนยัน เรียกใช้ docker compose config --volumes ก่อน เพื่อให้ทราบว่ารายการใดอาจได้รับผลกระทบ
ฉันสามารถเรียกใช้คำสั่งเดียวโดยไม่เริ่มต้น stack ทั้งหมดได้หรือไม่?
ได้ docker compose run --rm --no-deps web sh จะเริ่มต้น container เดียวจากคำจำกัดความ service ใน web ข้าม dependencies และลบ container เมื่อคุณออกจากการทำงาน ใช้ exec แทนเมื่อ container กำลังทำงานอยู่แล้ว เนื่องจาก exec จะเชื่อมต่อกับ process ที่กำลังทำงาน และแสดงสถานะจริงของ service