← กลับ
DockersystemdLinuxTroubleshooting

Restart Service ไหนดีระหว่าง docker.service vs docker.socket

systemctl restart docker บางครั้งไม่จบ container ก็ยังพัง — ความต่างระหว่าง 2 unit นี้และเมื่อไหร่ควร restart ตัวไหน

2025-10-30อ่าน 6 นาทีใหม่

ปัญหา

หลังเปลี่ยน /etc/docker/daemon.json แล้ว:

sudo systemctl restart docker

แต่บาง config ไม่ apply / container ค้าง / socket ใช้ไม่ได้

ทำไม? เพราะ Docker ไม่ใช่ unit เดียว — มี 2 unit ที่ทำงานคู่กัน

docker.service vs docker.socket

systemctl list-units --type=service,socket | grep docker

ผลลัพธ์:

docker.service    loaded active running   Docker Application Container Engine
docker.socket     loaded active running   Docker Socket for the API

docker.socket = systemd socket activation

  • listen /var/run/docker.sock ตลอดเวลา
  • ทำหน้าที่ "เปิด socket" รอการเชื่อมต่อ
  • ถ้ามีคน connect — start docker.service

docker.service = ตัว Docker daemon (dockerd) จริง

  • รัน container
  • จัดการ image / network / volume

ความสัมพันธ์: docker.socket start ก่อน — รับ connection — กระตุ้น docker.service ขึ้นมา

ทำไมถึงสำคัญ

Case 1: restart docker.service อย่างเดียว

sudo systemctl restart docker.service
  • docker.service หยุด → start ใหม่
  • docker.socket ยังทำงานอยู่ — เก็บ pending connection
  • container restart ตาม restart policy

ใช้ได้ในกรณีปกติ

Case 2: ต้อง restart docker.socket ด้วย

ถ้าเปลี่ยน path ของ socket หรือ permission:

{
  "hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]
}

แค่ restart docker.service ไม่พอ — docker.socket ยัง bind path เดิม

ต้อง restart ทั้งคู่:

sudo systemctl restart docker.socket docker.service

Case 3: docker.service start ไม่ขึ้น

$ sudo systemctl start docker.service
Job for docker.service failed

ดู error:

sudo journalctl -u docker.service -n 50

อาจเห็น:

listen unix /var/run/docker.sock: bind: address already in use

→ socket ที่ docker.socket ถืออยู่ยังไม่ release — stop socket ก่อน:

sudo systemctl stop docker.service docker.socket
sudo systemctl start docker.socket docker.service

ลำดับสำคัญ — socket ก่อน service

คำสั่งที่ใช้บ่อย

Restart ทั้งคู่ (แนะนำเมื่อสงสัย)

sudo systemctl restart docker.socket docker.service

ดู status

sudo systemctl status docker.service
sudo systemctl status docker.socket

ดู log แต่ละ unit

sudo journalctl -u docker.service -f      # daemon log
sudo journalctl -u docker.socket -f       # socket log

Disable / Enable

# enable ตอน boot
sudo systemctl enable docker.service docker.socket

# disable
sudo systemctl disable docker.service docker.socket

เปลี่ยน Daemon Config — ขั้นตอนที่ปลอดภัย

# 1. แก้ไฟล์
sudo nano /etc/docker/daemon.json

# 2. ตรวจ JSON syntax
sudo dockerd --validate-config
# หรือ
cat /etc/docker/daemon.json | jq .

# 3. restart
sudo systemctl restart docker.service

# 4. ตรวจว่า apply
docker info | grep -E "Storage|Logging|Cgroup"

ถ้า config ผิด syntax — docker.service start ไม่ขึ้น

  • ดู error: sudo journalctl -u docker.service -n 30
  • แก้ใน daemon.json — restart ใหม่

Container Restart Policy

ตอน Docker daemon restart — container จะ:

| Policy | พฤติกรรม | |---|---| | no (default) | ตายไปเลย ไม่ start อัตโนมัติ | | on-failure | start ถ้า exit code != 0 | | always | start ทุกครั้งที่ daemon up | | unless-stopped | start ยกเว้น stop ด้วยมือก่อน |

production แนะนำ unless-stopped — บอก daemon ว่า "ครั้งหน้า up อะ start ตัวฉันด้วย"

ใน compose:

services:
  app:
    image: myapp
    restart: unless-stopped

ปัญหา socket ที่เจอบ่อย

Permission denied

$ docker ps
permission denied while trying to connect to the Docker daemon socket

user ไม่อยู่ใน group docker:

sudo usermod -aG docker $USER
# logout-login ใหม่

หรือใช้ sudo:

sudo docker ps

Socket ไม่อยู่

$ docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock

ตรวจ:

# socket ทำงานอยู่มั้ย
sudo systemctl status docker.socket

# ไฟล์ socket อยู่จริงมั้ย
ls -la /var/run/docker.sock

ถ้าไม่มี — start:

sudo systemctl start docker.socket docker.service

Hang ตอน restart

ถ้า container เยอะ — restart นานเพราะ daemon รอ container shutdown ทีละตัว

ดู progress:

sudo journalctl -u docker.service -f

ถ้า hang นานเกิน — force kill (ระวัง! ข้อมูล container ปัจจุบันอาจหาย):

sudo systemctl kill -s SIGKILL docker.service
sudo systemctl restart docker.service

เคสพิเศษ: เปลี่ยน data-root

ตอนย้าย Docker directory (อ่านเพิ่ม):

sudo systemctl stop docker.service docker.socket
# ย้ายข้อมูล + แก้ daemon.json
sudo systemctl start docker.socket docker.service

ถ้า restart docker.service อย่างเดียว — daemon ยังใช้ socket ที่ socket unit ถือ ไม่กระทบ — แต่ data-root อาจ apply ถูก

ที่ดีคือ restart ทั้งคู่ให้ clean

Rootless Docker

ถ้าใช้ rootless Docker — unit อยู่ใน user systemd:

systemctl --user status docker.service
systemctl --user restart docker.service

ไม่ต้องใช้ sudo

Containerd / Snap

ระบบที่ใช้ snap install Docker หรือใช้ containerd ตรงๆ — unit name ต่างไป:

# snap
sudo systemctl restart snap.docker.dockerd

# containerd
sudo systemctl restart containerd

ตรวจชื่อ unit ที่มีจริง:

systemctl list-units | grep -i docker

Cheat Sheet

# restart ปลอดภัย (ทุก scenario)
sudo systemctl restart docker.socket docker.service

# stop / start ตามลำดับ
sudo systemctl stop docker.service docker.socket
sudo systemctl start docker.socket docker.service

# enable ตอน boot
sudo systemctl enable docker.service docker.socket

# status
sudo systemctl status docker.service docker.socket

# log
sudo journalctl -u docker.service -n 50
sudo journalctl -u docker.socket -n 50

TLDR

  • docker.service = daemon รัน container
  • docker.socket = listener ของ /var/run/docker.sock
  • ปกติ restart docker.service พอ
  • เปลี่ยน path/permission ของ socket → restart ทั้งคู่
  • สงสัยเมื่อไหร่ → restart ทั้งคู่ ปลอดภัยกว่า

สรุป

Docker บน Linux ใช้ systemd socket activation — มี 2 unit ที่ต้องรู้จัก

Pattern ที่จำง่าย: socket ก่อน service เวลา start และ service ก่อน socket เวลา stop (แต่จริงๆ systemctl handle ลำดับให้)

ถ้า restart แล้วยังพัง — ดู journalctl -u docker.service เกือบทุกครั้งบอก root cause ตรงๆ

← ดูบทความอื่น