Run Container: Interactive & Detached
เมื่อเข้าใจว่า interactive mode กับ detached mode ต่างกันอย่างไร คุณจะเลือกใช้คำสั่ง docker run ได้อย่างถูกต้องในทุกสถานการณ์ ทั้งการทดลองใช้งาน การ debug และการรัน service ต่อเนื่อง
ภาพจำสำคัญบทนี้
-it = โต้ตอบกับ container โดยตรง (explore, debug) | -d = ทำงานเบื้องหลัง (service ที่รันต่อเนื่อง) | ถ้า process หลักจบ container จะ stop ทันที
ส่วนที่ 1
การ run container คืออะไร
Container คือโปรแกรมที่ทำงานในสภาพแวดล้อมแยกออกมาจากเครื่องโฮสต์ การสั่ง run container คือการนำ image มาสร้างเป็น container ที่พร้อมทำงานจริง เปรียบได้กับการเปิดแอปพลิเคชันขึ้นมา image เหมือนไฟล์ติดตั้ง (.exe) ส่วน container คือแอปที่กำลังรันอยู่ในขณะนั้น คำสั่ง docker run ทำสองอย่างในคำสั่งเดียว คือสร้าง container ใหม่จาก image และเริ่มรันทันที
ประเด็นที่ 1
Image = แม่พิมพ์ที่ไม่เคยเปลี่ยน พร้อมให้สร้าง container ได้ทุกเมื่อ
ประเด็นที่ 2
Container = instance ที่สร้างจาก image และทำงานอยู่จริงในเครื่องของเรา
ประเด็นที่ 3
docker run = คำสั่งที่สร้าง + เริ่มรัน container ในคำสั่งเดียว
ส่วนที่ 2
ทำไมต้องรู้เรื่องการ run container
docker run เป็นคำสั่งพื้นฐานที่สุดใน Docker แทบทุกงาน ไม่ว่าจะเป็นการพัฒนา การทดสอบ หรือการ deploy ล้วนเริ่มต้นที่นี่ Docker มีสองโหมดหลักที่แตกต่างกันมาก ถ้าเลือกผิดโหมด terminal อาจถูก block หรือ service อาจไม่ทำงานตามที่คาดหวัง การเข้าใจความต่างตั้งแต่ต้นจะช่วยประหยัดเวลาได้มาก
- รัน service อย่าง nginx, postgres, redis ให้ทำงานในเครื่องเรา
- ทดสอบแอปในสภาพแวดล้อมที่แยกจากเครื่องโฮสต์
- เรียนรู้ระบบปฏิบัติการหรือ tool ใหม่โดยไม่ต้องติดตั้งลงเครื่อง
- ทำ CI/CD และ deployment ในสภาพแวดล้อมที่ควบคุมได้
ส่วนที่ 3
interactive mode คืออะไร
interactive mode หรือโหมดโต้ตอบ คือการรัน container แบบที่ terminal ของเราถูก attach หรือเชื่อมต่อเข้าไปใน container โดยตรง เราสามารถพิมพ์คำสั่งเข้าไปใน container และเห็น output กลับมาได้ทันทีแบบ real-time เหมือนกับการนั่งอยู่หน้าเครื่องที่ติดตั้ง Ubuntu แล้วเปิด terminal ขึ้นมาใช้งาน จุดสำคัญ: เมื่อเราออกจาก shell ด้วยคำสั่ง exit หรือกด Ctrl+D container จะหยุดทำงานทันที เพราะ process หลักของ container คือ shell นั้นเอง
รัน container จาก image ubuntu แล้วเปิด bash shell เพื่อโต้ตอบกับ container โดยตรง terminal ของเราจะเชื่อมต่อเข้าไปทันที
ส่วนที่ 4
detached mode คืออะไร
detached mode หรือโหมดเบื้องหลัง คือการรัน container ให้ทำงานอยู่เบื้องหลัง โดยที่ terminal ของเราไม่ถูก attach เข้าไป หลังจากรันคำสั่ง terminal จะแสดง container ID สั้น ๆ แล้วกลับมาให้เราใช้งานได้ทันที container ยังคงทำงานอยู่เบื้องหลังต่อไปโดยไม่ขึ้นกับ terminal ของเรา เหมาะสำหรับ service ที่ต้องทำงานต่อเนื่องโดยไม่มีการโต้ตอบกับผู้ใช้ เช่น web server, database หรือ message queue
รัน nginx แบบเบื้องหลัง พร้อมตั้งชื่อ container ว่า my-nginx terminal จะกลับมาทันทีหลังแสดง container ID
ส่วนที่ 5
โครงสร้างคำสั่ง docker run
คำสั่ง docker run มีสามส่วนหลัก ส่วนแรกคือ options ที่บอก Docker ว่าต้องการรันในโหมดไหนและตั้งค่าอะไร ส่วนที่สองคือชื่อ image ที่ต้องการสร้าง container ส่วนสุดท้ายคือคำสั่งที่ต้องการรันใน container ซึ่งจะ override คำสั่งเดิมที่กำหนดใน Dockerfile
ส่วนใน [ ] หมายถึง optional สามารถใส่หรือไม่ใส่ก็ได้ IMAGE คือส่วนเดียวที่ต้องระบุเสมอ
ส่วนที่ 6
options สำคัญที่ต้องรู้จัก
options แต่ละตัวมีหน้าที่ต่างกันและมักใช้ร่วมกัน ตารางด้านล่างสรุป options ที่ใช้บ่อยที่สุดพร้อมคำอธิบายและตัวอย่าง
| Option | ความหมาย | ตัวอย่าง |
|---|---|---|
| -i | เปิด stdin ให้ container รับ input จาก terminal ได้ | docker run -i ubuntu |
| -t | สร้าง pseudo-TTY หรือ terminal เสมือนใน container | docker run -t ubuntu |
| -it | ใช้ทั้ง -i และ -t พร้อมกัน เพื่อโต้ตอบกับ shell ใน container | docker run -it ubuntu bash |
| -d | รัน container เบื้องหลัง (detached mode) terminal กลับมาทันที | docker run -d nginx |
| --name | ตั้งชื่อให้ container แทน ID สุ่มที่ Docker สร้างให้ | docker run --name my-app nginx |
| --rm | ลบ container อัตโนมัติเมื่อ container หยุดทำงาน เหมาะกับการทดสอบ | docker run --rm ubuntu bash |
| -p | เชื่อม port ของ container เข้ากับ port ของเครื่องโฮสต์ | docker run -p 8080:80 nginx |
ส่วนที่ 7
ทำไม -i และ -t ต้องใช้ร่วมกันเสมอ
สองตัวนี้ทำงานแตกต่างกัน -i (interactive) ทำให้ stdin ของ container ยังคงเปิดอยู่เพื่อรับ input จากเรา ส่วน -t (tty) สร้าง terminal เสมือนที่ทำให้ output แสดงผลสวยงามและมี prompt ของ shell ปรากฏขึ้นมา ถ้าใช้แค่ -i เราพิมพ์คำสั่งได้แต่ไม่เห็น prompt ถ้าใช้แค่ -t มี terminal แต่รับ input ไม่ถูกต้อง จึงต้องใช้ -it ร่วมกันเสมอเมื่อต้องการโต้ตอบกับ container
- -i เพียงอย่างเดียว: stdin เปิดแต่ไม่มี prompt — พิมพ์คำสั่งได้แต่ดูยากมาก
- -t เพียงอย่างเดียว: มี terminal เสมือนแต่ stdin ไม่ได้รับ input อย่างถูกต้อง
- -it ร่วมกัน: stdin เปิด + มี terminal เสมือน — ใช้งาน shell ได้สมบูรณ์แบบ
ส่วนที่ 8
ตัวอย่างที่ 1 — interactive mode กับ Ubuntu
ตัวอย่างนี้เป็นการรัน container จาก Ubuntu image และเปิด bash shell เพื่อทดลองใช้งาน Linux command ในสภาพแวดล้อมที่แยกออกมา เหมาะสำหรับการทดลองใช้ Linux โดยไม่ต้องติดตั้งบนเครื่อง หรือการตรวจสอบ environment ของ container สังเกตว่า prompt จะเปลี่ยนจาก terminal เครื่องเราเป็น root@[containerID]:/# ซึ่งแสดงว่าเราอยู่ใน container แล้ว
เมื่อรันคำสั่งนี้ terminal จะเชื่อมต่อเข้า bash shell ของ Ubuntu container ทันที พิมพ์ exit เมื่อต้องการออก
ส่วนที่ 9
ตัวอย่างที่ 2 — interactive mode แบบทดลองชั่วคราวด้วย Alpine
Alpine Linux เป็น image ขนาดเล็กมาก (ประมาณ 5 MB) เหมาะสำหรับการทดสอบ option --rm ทำให้ Docker ลบ container ออกอัตโนมัติทันทีที่เราพิมพ์ exit ไม่ต้องรัน docker rm ทีหลัง เหมาะสำหรับการทดลองแบบ one-off ที่ไม่ต้องการเก็บ container ไว้
--rm ทำให้ container ถูกลบออกทันทีเมื่อ sh process จบลง Alpine ใช้ sh แทน bash เนื่องจากเป็น image ขนาดเล็ก
ส่วนที่ 10
ตัวอย่างที่ 3 — detached mode กับ Nginx
Nginx เป็น web server ที่ต้องทำงานต่อเนื่องรอรับ request จาก browser การรันแบบ interactive จะทำให้ terminal ของเราถูก block อยู่ตลอดเวลา จึงต้องใช้ detached mode แทน หลังจากรันคำสั่งนี้ terminal จะกลับมาทันที และ nginx จะทำงานอยู่เบื้องหลัง รอรับ request ที่ port 8080 ของเครื่องเรา ลองเปิด browser ไปที่ localhost:8080 เพื่อดู Nginx welcome page
-d รันเบื้องหลัง / --name my-nginx ตั้งชื่อให้จำง่าย / -p 8080:80 ส่ง port 80 ของ container ออกมาที่ port 8080 ของเครื่องเรา
ส่วนที่ 11
เปรียบเทียบ interactive กับ detached แบบชัดเจน
ทั้งสองโหมดใช้กับสถานการณ์ต่างกันโดยสิ้นเชิง ตารางด้านล่างเปรียบเทียบความแตกต่างหลักเพื่อช่วยตัดสินใจว่าควรใช้โหมดไหน
| ด้าน | interactive mode (-it) | detached mode (-d) |
|---|---|---|
| terminal หลังรัน | terminal ถูก attach เข้า container | terminal กลับมาทันที |
| การโต้ตอบ | พิมพ์คำสั่งในหน้าต่างเดิมได้เลย | ต้องใช้ docker exec -it เพื่อเข้าไป |
| เมื่อออกจาก shell | container หยุดทำงานทันที | container ยังทำงานต่อเนื่อง |
| เหมาะกับ | ทดสอบ สำรวจ debug ชั่วคราว | service ที่ต้องทำงานต่อเนื่อง |
| ตัวอย่าง image | ubuntu, alpine, python, node | nginx, postgres, redis, mysql |
ส่วนที่ 12
เมื่อ process หลักจบ container จะเกิดอะไรขึ้น
Docker ไม่ได้ monitor ทั้ง container แต่ monitor เฉพาะ process หลัก (PID 1) ที่ถูกรันตอน start container เมื่อ process นั้นจบลงไม่ว่าด้วยเหตุผลใด container จะ stop โดยอัตโนมัติทันที ใน interactive mode พอเราพิมพ์ exit จาก bash หรือ sh นั้นคือ process หลักจบ container จึง stop ใน detached mode ถ้า nginx crash หรือ database ปิดตัว container ก็จะ stop เช่นกัน แต่ container ที่ stop ยังไม่ถูกลบออก ข้อมูลยังคงอยู่และสามารถรัน docker start ใหม่ได้
- PID 1 = ชีวิตของ container ถ้า process หลักจบ container จะ stop ตามทันที
- container stopped ≠ container deleted ข้อมูลยังอยู่ แต่ไม่ได้ทำงาน
- docker start [name] ใช้รีสตาร์ท container ที่ stopped อยู่
- --rm ใช้เมื่อต้องการให้ Docker ลบ container อัตโนมัติเมื่อ stop
ส่วนที่ 13
ตรวจสอบและหยุด container
หลังจากรัน container แบบ detached เราต้องใช้คำสั่งแยกต่างหากเพื่อดูสถานะและหยุดการทำงาน docker stop ส่ง signal SIGTERM ให้ process จบอย่างสุภาพก่อน ต่างจาก docker kill ที่หยุดทันทีโดยไม่รอ
docker ps แสดง container ที่ running / docker ps -a แสดงทั้งหมดรวม stopped / docker stop หยุดอย่างสุภาพ
ส่วนที่ 14
ข้อผิดพลาดที่พบบ่อยในการ run container
ผู้เริ่มต้นมักเจอปัญหาเดิม ๆ ซ้ำ ๆ ตรวจสอบรายการด้านล่างก่อน เพื่อประหยัดเวลาในการแก้ปัญหา
- container เด้งออกทันที — process หลักจบเร็วเกินไป เช่น docker run ubuntu ไม่มี bash ให้ค้างไว้ ต้องระบุ command เช่น bash หรือใช้ sleep infinity
- ชื่อ container ซ้ำ — ถ้าใช้ --name ซ้ำกับที่มีอยู่ Docker จะ error ให้รัน docker rm [name] ก่อนหรือเปลี่ยนชื่อ
- port ชน — ถ้า port 8080 บนเครื่องโฮสต์ถูกใช้งานแล้ว Docker จะ error ให้เปลี่ยน host port เช่น -p 9090:80
- ลืมใส่ -it แล้วต้องการ shell — ถ้ารัน detached ไปแล้วใช้ docker exec -it [name] bash เพื่อเข้าไปใน container
- image ไม่มีในเครื่อง — Docker จะ pull อัตโนมัติ แต่ถ้าชื่อ image ผิดจะ error ให้ตรวจชื่อบน Docker Hub
ส่วนที่ 15
สถานการณ์จริงในการใช้งานทั้งสองโหมด
ในงานจริงนักพัฒนาใช้ทั้งสองโหมดสลับกันตามสถานการณ์ ตัวอย่างด้านล่างแสดงให้เห็นว่าโหมดไหนเหมาะกับงานแบบไหน
ประเด็นที่ 1
Debug แอป: รัน container ของแอปแบบ interactive เพื่อตรวจสอบ environment variable และไฟล์ config ว่าถูกต้องก่อน deploy จริง
ประเด็นที่ 2
Local development: รัน postgres หรือ mysql แบบ detached ให้พร้อมรับ connection จาก backend ที่กำลัง dev อยู่โดยไม่ต้องติดตั้ง database บนเครื่องจริง
ประเด็นที่ 3
ทดสอบ tool: รัน container แบบ -it --rm เพื่อทดลองใช้งาน CLI tool เช่น curl, jq หรือ python โดยไม่ต้องติดตั้งและไม่ทิ้งร่องรอยไว้
ส่วนที่ 16
สรุปท้ายบท — จำแค่นี้ก็พอสำหรับการเริ่มต้น
interactive และ detached เป็นสองโหมดหลักของการรัน container แต่ละโหมดมีจุดประสงค์ชัดเจน กฎง่าย ๆ คือ ถ้าต้องการพิมพ์คำสั่งใน container ใช้ -it ถ้าต้องการให้ service ทำงานในเบื้องหลังใช้ -d
- -it = ต้องการโต้ตอบกับ container แบบ real-time เช่น explore, debug, test
- -d = ต้องการให้ service ทำงานเบื้องหลัง เช่น web server, database, queue
- --name = ตั้งชื่อเพื่อให้จำง่าย ไม่ต้องจำ container ID สุ่ม
- --rm = ลบ container อัตโนมัติเมื่อจบ เหมาะกับการทดสอบชั่วคราว
- docker ps = ตรวจสอบ container ที่กำลังรัน
- docker stop = หยุด container อย่างสุภาพโดยส่ง SIGTERM
ส่วนที่ 17
แบบฝึกหัด 3 ข้อ พร้อมแนวเฉลย
ลองทำแบบฝึกหัดด้านล่างด้วยตัวเองก่อนดูเฉลย การลงมือทำจะช่วยให้จำคำสั่งได้นานกว่าการอ่านเฉย ๆ แต่ละข้อใช้เวลาไม่เกิน 5 นาที