Container Lifecycle
วงจรชีวิตของ container เริ่มจากการสร้าง รัน หยุด ไปจนถึงลบออก การเข้าใจแต่ละสถานะและคำสั่งที่ใช้เปลี่ยน state จะทำให้คุณควบคุม container ได้อย่างมั่นใจในทุกสถานการณ์
ภาพจำสำคัญบทนี้
stop ≠ delete | ข้อมูลหายเฉพาะเมื่อ docker rm | docker ps -a เท่านั้นที่เห็น container ทุก state | docker restart = stop + start
ส่วนที่ 1
Container lifecycle คืออะไร
ทุกสิ่งมีวงจรชีวิต container ก็เช่นกัน วงจรชีวิต (lifecycle) ของ container คือลำดับสถานะที่ container ผ่านตั้งแต่เกิดขึ้นจนสิ้นสุด ตั้งแต่การสร้างจาก image การรันทำงานจริง การหยุดชั่วคราว การหยุดสนิท ไปจนถึงการลบออกจากระบบ การเข้าใจ lifecycle ช่วยให้รู้ว่าต้องใช้คำสั่งไหนในแต่ละสถานการณ์ ข้อมูลอยู่หรือหายไปหลังจาก stop และจะ restart หรือ remove container อย่างถูกต้องได้อย่างไร
ประเด็นที่ 1
lifecycle = ลำดับสถานะทั้งหมดที่ container ผ่าน ตั้งแต่สร้างจนลบออก
ประเด็นที่ 2
แต่ละสถานะมีคำสั่งเฉพาะที่ใช้เข้าและออกจากสถานะนั้น
ประเด็นที่ 3
การเข้าใจ lifecycle ทำให้แก้ปัญหา debug และจัดการ container ได้อย่างมั่นใจ
ส่วนที่ 2
ทบทวน: image กับ container ต่างกันอย่างไร
ก่อนเข้า lifecycle ขอทบทวนความต่างของ image กับ container อย่างรวดเร็ว เพราะทั้งสองเป็นจุดเริ่มต้นของ lifecycle Image คือแม่พิมพ์ที่ไม่เปลี่ยนแปลง เหมือนสูตรอาหารที่เขียนไว้บนกระดาษ ส่วน container คือของจริงที่ถูกสร้างจาก image นั้น เหมือนอาหารที่ถูกปรุงขึ้นมาจริง ๆ แล้ววางบนโต๊ะ container มี state เปลี่ยนได้ระหว่างใช้งาน แต่ image ไม่เคยเปลี่ยน
- Image = read-only template ไม่เปลี่ยนแปลง ใช้สร้าง container ได้หลายตัวพร้อมกัน
- Container = instance ที่รันจริงจาก image มี state เป็นของตัวเอง และเปลี่ยนสถานะได้
- docker run [image] = สร้าง container ใหม่จาก image แล้วรันทันที
ส่วนที่ 3
ภาพรวมวงจรชีวิต container ทั้งหมด
วงจรชีวิตของ container ไม่ได้เป็นเส้นตรงเสมอไป container สามารถถูก restart, pause, หรือรัน start ซ้ำได้หลายรอบก่อนจะถูกลบออก แผนภาพด้านล่างแสดง state หลักทั้งหมดพร้อมคำสั่งที่ใช้ transition ระหว่าง state
คำสั่ง transition ทั้งหมด
ส่วนที่ 4
สถานะ created — สร้าง container แต่ยังไม่รัน
สถานะ created เกิดขึ้นเมื่อเราสั่ง docker create Docker จะสร้าง container layer ขึ้นมาจาก image กำหนด container ID และเตรียม network ไว้ แต่ยังไม่เริ่ม process ใด ๆ ภายใน container ยังไม่ใช้ CPU หรือ RAM ณ จุดนี้ ในงานจริง docker create ไม่ค่อยถูกใช้โดยตรง เพราะส่วนมากเราใช้ docker run ซึ่ง create + start ในคำสั่งเดียว แต่การเข้าใจ created state ช่วยให้เข้าใจ lifecycle ได้ครบถ้วน
docker create เตรียม container ไว้แต่ยังไม่เริ่มทำงาน ต้องสั่ง docker start ตามมาภายหลัง
ส่วนที่ 5
สถานะ running — container กำลังทำงานอยู่
สถานะ running คือสถานะที่ container ทำงานจริง process หลัก (PID 1) กำลังรันอยู่ ใช้ CPU และ RAM ตามปกติ container ในสถานะนี้พร้อมรับ request, ประมวลผล, และสร้าง output มีสองทางเข้าสู่ running state: ใช้ docker run (create + start พร้อมกัน) หรือสั่ง docker start ต่อจาก created หรือ stopped state
docker run เหมาะกับการสร้าง container ใหม่ ส่วน docker start เหมาะกับการรีสตาร์ท container ที่มีอยู่แล้ว
ส่วนที่ 6
สถานะ paused — หยุดชั่วคราวโดยไม่สิ้นสุด process
สถานะ paused คือการหยุด container ชั่วคราวโดยใช้ Linux SIGSTOP signal Process ยังอยู่ในหน่วยความจำ แต่ CPU ถูก suspend ทั้งหมด ข้อมูลใน RAM ยังคงอยู่ครบถ้วน paused ต่างจาก stopped ตรงที่ process ไม่ได้จบ แค่หยุดรันชั่วคราว สามารถ unpause แล้วทำงานต่อได้ทันทีจากจุดที่หยุดไว้ ใช้น้อยมากในงานจริง ส่วนมากใช้เพื่อ debug หรือประหยัด CPU ชั่วคราว
docker pause ระงับ CPU โดยไม่ kill process ข้อมูลใน RAM ยังอยู่ครบ พร้อม resume ทันทีที่ unpause
ส่วนที่ 7
สถานะ stopped — container หยุดทำงานแต่ยังอยู่ในระบบ
สถานะ stopped (หรือที่ docker ps -a แสดงว่า Exited) คือ container ที่ process หลักจบลงแล้ว ไม่ว่าจะเกิดจากการสั่ง docker stop, process crash, หรือการพิมพ์ exit ใน interactive shell สิ่งสำคัญที่ต้องเข้าใจ: container ที่ stopped ยังคงอยู่ในระบบ ข้อมูลใน writable layer ยังอยู่ครบ สามารถสั่ง docker start เพื่อรันใหม่ได้ทุกเมื่อ container จะหายไปจาก docker ps แต่ยังปรากฏใน docker ps -a
docker stop รอ grace period (default 10 วินาที) ก่อน SIGKILL / docker kill หยุดทันที ใช้เมื่อ container ไม่ตอบสนอง
ส่วนที่ 8
docker restart — รีสตาร์ท container ในคำสั่งเดียว
docker restart คือ shortcut ของการสั่ง stop แล้ว start ต่อเนื่องกัน Docker จะส่ง SIGTERM ให้ process หยุดก่อน จากนั้นเริ่ม process ใหม่จากคำสั่งเดิมที่กำหนดไว้ใน image ข้อมูลใน writable layer ยังคงอยู่ครบ ใช้บ่อยเมื่อต้องการ apply การตั้งค่าใหม่ที่ต้องการ restart หรือเมื่อ service ค้างและต้องการรีเซ็ต
docker restart = docker stop + docker start ในคำสั่งเดียว ข้อมูลใน writable layer ยังคงอยู่หลัง restart
ส่วนที่ 9
สถานะ removed — ลบ container ออกจากระบบถาวร
สถานะ removed คือจุดสิ้นสุดของ lifecycle container ถูกลบออกจากระบบโดยสมบูรณ์ ทั้ง writable layer และข้อมูลที่เขียนไว้ใน container จะหายไปทั้งหมด สำคัญ: ต้อง stop container ก่อนจึงจะ rm ได้ (เว้นแต่ใช้ docker rm -f ซึ่ง force stop + remove พร้อมกัน) เมื่อลบแล้วจะไม่ปรากฏใน docker ps -a อีกต่อไป
docker rm ลบข้อมูล writable layer ของ container ถาวร แต่ image ที่ใช้สร้างยังอยู่และสร้าง container ใหม่ได้เสมอ
ส่วนที่ 10
หลังจาก stop แล้วข้อมูลใน container ยังอยู่ไหม
นี่คือหนึ่งในจุดที่ผู้เริ่มต้นมักสับสนที่สุด คำตอบคือ ขึ้นอยู่กับสถานะ stop หรือ remove ข้อมูลใน container แบ่งเป็นสองส่วน: image layers ที่เป็น read-only (ไม่เคยหายไปเพราะอยู่กับ image) และ writable layer ที่ container เขียนเพิ่มระหว่างทำงาน
- หลัง docker stop: ข้อมูลใน writable layer ยังอยู่ครบ — container แค่ไม่ทำงาน สามารถ start ใหม่ได้
- หลัง docker rm: ข้อมูลใน writable layer หายไปถาวร — image ยังอยู่ แต่ข้อมูลที่เขียนไปแล้วหายหมด
- ต้องการเก็บข้อมูลข้าม remove? ต้องใช้ Docker Volume หรือ Bind Mount (เรื่องของบทถัดไป)
ส่วนที่ 11
ความต่างของ stop กับ remove
ผู้เริ่มต้นมักเข้าใจผิดว่า stop กับ remove คือสิ่งเดียวกัน แต่ทั้งสองต่างกันโดยสิ้นเชิง ตารางด้านล่างเปรียบเทียบให้เห็นชัดเจน
| ด้าน | docker stop | docker rm |
|---|---|---|
| process หยุดทำงาน | ใช่ | ใช่ (ถ้ายัง running ต้อง rm -f) |
| container ยังอยู่ในระบบ | ใช่ ดูได้จาก docker ps -a | ไม่ ลบออกถาวร |
| ข้อมูลใน writable layer | ยังอยู่ครบ | หายไปถาวร |
| สามารถ start ใหม่ได้ | ได้ด้วย docker start | ไม่ได้ container ถูกลบแล้ว |
| ใช้เมื่อ | หยุดพักชั่วคราว ยังต้องการทีหลัง | ไม่ต้องการ container นี้อีกแล้ว |
ส่วนที่ 12
คำสั่งทั้งหมดที่เกี่ยวกับ lifecycle
ตารางด้านล่างสรุปคำสั่งทุกตัวที่ใช้จัดการ lifecycle ของ container พร้อม state ที่ได้รับผลและตัวอย่างการใช้งาน
| คำสั่ง | ผลลัพธ์ (state เปลี่ยนเป็น) | ตัวอย่าง |
|---|---|---|
| docker create | created | docker create --name demo nginx |
| docker run | running (create + start) | docker run -d --name demo nginx |
| docker start | running | docker start demo |
| docker stop | stopped | docker stop demo |
| docker kill | stopped (ทันที) | docker kill demo |
| docker restart | running (stop → start) | docker restart demo |
| docker pause | paused | docker pause demo |
| docker unpause | running | docker unpause demo |
| docker rm | removed (ถาวร) | docker rm demo |
| docker ps | — (ดู running) | docker ps |
| docker ps -a | — (ดูทุก state) | docker ps -a |
ส่วนที่ 13
ตัวอย่าง: lifecycle ของ container 1 ตัวแบบครบลำดับ
ตัวอย่างด้านล่างแสดงการเดินทางของ container 1 ตัวตลอด lifecycle ตั้งแต่สร้างจนลบออก พร้อม output ที่ควรเห็นในแต่ละขั้นตอน ลองรันตามเพื่อให้เห็นภาพจริง
ลองรันตามทีละขั้นเพื่อเห็น state เปลี่ยนจริง สังเกต output ของ docker ps และ docker ps -a ในแต่ละจุด
ส่วนที่ 14
ข้อผิดพลาดที่ผู้เริ่มต้นมักเจอ
ข้อผิดพลาดเหล่านี้พบบ่อยมากในช่วงเริ่มต้น เข้าใจก่อนจะประหยัดเวลาได้มาก
- คิดว่า stop = delete: docker stop แค่หยุด process ข้อมูลยังอยู่ ต้อง docker rm จึงจะลบจริง
- docker ps ไม่เห็น container ที่ stop แล้ว: ต้องใช้ docker ps -a เพื่อดู container ทุก state รวมถึง stopped
- rm container ที่ยัง running: ต้อง stop ก่อน หรือใช้ docker rm -f เพื่อ force remove
- สร้าง container ชื่อซ้ำ: Docker ไม่ยอมให้มีชื่อซ้ำกัน แม้ container นั้นจะ stopped อยู่ก็ตาม ต้อง docker rm ก่อน
- หวังว่าข้อมูลจะอยู่หลัง rm: ข้อมูลที่เขียนใน container หายไปพร้อม docker rm ต้องใช้ Volume ถ้าอยากเก็บไว้
ส่วนที่ 15
สถานการณ์จริงที่ใช้ lifecycle จัดการ container
ในงานจริงนักพัฒนาและ devops ใช้คำสั่ง lifecycle เหล่านี้ตลอดเวลา ตัวอย่างด้านล่างแสดงให้เห็นว่า lifecycle concept ถูกนำไปใช้อย่างไร
ประเด็นที่ 1
Local dev: รัน postgres แบบ detached ระหว่างพัฒนา เมื่อหยุดพักใช้ docker stop เพื่อประหยัด resource จากนั้น docker start เมื่อกลับมาทำงาน ข้อมูล dev ยังอยู่ครบ
ประเด็นที่ 2
ทดสอบ config ใหม่: docker restart เพื่อ reload service หลังแก้ config โดยไม่ต้องสร้าง container ใหม่ เหมาะกับ nginx หรือ app server ที่อ่าน config ตอน start
ประเด็นที่ 3
Clean up หลังทดสอบ: docker rm -f ลบ container ทดสอบทิ้งทันที หรือใช้ docker container prune เพื่อลบ container ที่ stopped ทั้งหมดในครั้งเดียว
ส่วนที่ 16
สรุปท้ายบท — จำ lifecycle ให้ขึ้นใจ
วงจรชีวิตของ container ไม่ซับซ้อน เพียงจำ state หลัก 4 ตัวและคำสั่งที่ใช้เปลี่ยน state แต่ละตัว กฎง่าย ๆ ที่ช่วยได้มาก: stop ≠ delete และข้อมูลหายเฉพาะเมื่อ rm เท่านั้น
- created → running: docker run (สร้าง + รัน) หรือ docker start (รัน container ที่มีอยู่)
- running → stopped: docker stop (สุภาพ) หรือ docker kill (ทันที)
- stopped → running: docker start (รันใหม่ ข้อมูลยังอยู่)
- running → removed: docker stop แล้ว docker rm หรือ docker rm -f
- docker ps = ดู running เท่านั้น / docker ps -a = ดูทุก state
- ข้อมูลหายถาวรเฉพาะเมื่อ docker rm ไม่ใช่เมื่อ docker stop
ส่วนที่ 17
แบบฝึกหัด 3 ข้อ พร้อมแนวเฉลย
ลองทำแบบฝึกหัดด้านล่างด้วยตัวเองก่อนดูเฉลย แต่ละข้อออกแบบให้ครอบคลุม lifecycle concept ที่สำคัญที่สุด