Chapter 07

Troubleshooting

Debug commands, common errors, và cách xử lý các vấn đề thường gặp

Debug Commands Cheatsheet

Những lệnh cần biết khi gặp sự cố:

Bash
# ══════════════════════════════════════
# TRẠNG THÁI & LOGS
# ══════════════════════════════════════

# Xem status tất cả containers (bao gồm health)
docker compose ps -a

# Xem logs service bị lỗi (100 dòng cuối)
docker compose logs --tail=100 backend

# Follow logs real-time
docker compose logs -f backend

# Xem events (start, stop, die, health_status)
docker compose events

# ══════════════════════════════════════
# TRUY CẬP VÀO CONTAINER
# ══════════════════════════════════════

# Shell vào container đang chạy
docker compose exec backend bash
docker compose exec postgres psql -U myapp_user -d myapp_db
docker compose exec redis redis-cli -a $REDIS_PASSWORD

# Shell vào container đã dừng (debug crash)
docker compose run --rm backend bash

# ══════════════════════════════════════
# NETWORK & CONNECTIVITY
# ══════════════════════════════════════

# Kiểm tra DNS resolution trong container
docker compose exec backend nslookup postgres
docker compose exec backend ping postgres -c 3

# Kiểm tra port connectivity
docker compose exec backend curl -v http://postgres:5432

# Liệt kê networks và containers
docker network ls
docker network inspect myapp_data-net

# ══════════════════════════════════════
# TÀI NGUYÊN
# ══════════════════════════════════════

# Real-time CPU, Memory, Network I/O
docker stats --no-stream

# Disk usage (images, containers, volumes)
docker system df

# Chi tiết disk usage
docker system df -v

# Xem disk space trên host
df -h

Quy trình xử lý sự cố

Khi hệ thống gặp vấn đề, đi theo quy trình sau:

docker compose ps
Check status
Logs
Tìm error message
Exec
Vào container debug
Fix & Restart
Sửa lỗi, restart

Lỗi thường gặp

Container restart loop (Restarting) Critical +

Triệu chứng: docker compose ps cho thấy container liên tục Restarting.

Nguyên nhân phổ biến:

  • App crash ngay khi khởi động (missing config, bad connection string)
  • Port đã bị sử dụng bởi process khác
  • Thiếu environment variables bắt buộc
  • Image build lỗi nhưng Compose vẫn cố start

Cách xử lý:

Bash
# 1. Xem logs để tìm error message
docker compose logs --tail=50 backend

# 2. Nếu container crash quá nhanh, xem exit code
docker compose ps -a
# Exit code 1 = app error, 137 = OOM killed, 139 = segfault

# 3. Chạy container ở foreground để xem output
docker compose up backend  # Không dùng -d

# 4. Shell vào image để debug
docker compose run --rm --entrypoint bash backend
Connection refused (PostgreSQL/Redis) Network +

Triệu chứng: API log: Npgsql.NpgsqlException: Failed to connect to postgres:5432

Nguyên nhân phổ biến:

  • PostgreSQL container chưa ready (chưa qua health check)
  • Sai tên service trong connection string (case-sensitive)
  • Containers không cùng Docker network
  • PostgreSQL đang init database lần đầu (chậm)

Cách xử lý:

Bash
# 1. Kiểm tra PostgreSQL đã ready chưa
docker compose ps postgres
# Phải hiện (healthy), không phải (health: starting)

# 2. Test kết nối từ API container
docker compose exec backend bash
apt-get update && apt-get install -y postgresql-client
psql -h postgres -U myapp_user -d myapp_db

# 3. Kiểm tra network
docker network inspect myapp_data-net
# Đảm bảo cả backend và postgres đều trong network

# 4. Kiểm tra env vars
docker compose exec backend env | grep Connection
Port already in use Host +

Triệu chứng: Bind for 0.0.0.0:80 failed: port is already allocated

Nguyên nhân: Port 80 hoặc 443 đang bị chiếm bởi process khác (Apache, Nginx trên host, hoặc container cũ).

Bash
# 1. Tìm process chiếm port
sudo lsof -i :80
sudo ss -tlnp | grep :80

# 2. Nếu là Apache/Nginx trên host
sudo systemctl stop apache2
sudo systemctl disable apache2

# 3. Nếu là container cũ
docker ps -a | grep 80
docker rm -f container_id

# 4. Hoặc đổi host port
# ports: "8080:80"  thay vì  "80:80"
Out of disk space Resource +

Triệu chứng: Builds fail, containers crash, no space left on device.

Nguyên nhân: Docker images, build cache, và container logs tích tụ theo thời gian.

Bash
# 1. Kiểm tra disk usage
df -h
docker system df

# 2. Dọn dẹp Docker (an toàn)
# Xóa dangling images (không gắn tag)
docker image prune -f

# Xóa build cache
docker builder prune -f

# Xóa stopped containers
docker container prune -f

# 3. Dọn dẹp mạnh tay (CẨN THẬN!)
# Xóa TẤT CẢ images, networks không sử dụng
docker system prune -a -f
# KHÔNG thêm --volumes trừ khi muốn mất data!

Phòng tránh: Cấu hình log rotation, dọn build cache định kỳ, và monitor disk usage.

Permission denied Filesystem +

Triệu chứng: Container log: Permission denied khi đọc/ghi files.

Nguyên nhân: Non-root user trong container không có quyền truy cập bind mount hoặc volume.

Bash
# 1. Kiểm tra UID/GID trong container
docker compose exec backend id
# uid=1001(appuser) gid=1001(appuser)

# 2. Sửa ownership trên host
sudo chown -R 1001:1001 ./data/

# 3. Hoặc set user trong Dockerfile
# RUN chown -R appuser:appuser /app

# 4. Với PostgreSQL volume, KHÔNG chown
# PostgreSQL tự quản lý permissions trong volume
Nginx 502 Bad Gateway Proxy +

Triệu chứng: Truy cập web thấy "502 Bad Gateway".

Nguyên nhân: Nginx không kết nối được đến upstream (frontend hoặc backend container).

Bash
# 1. Kiểm tra upstream containers còn chạy không
docker compose ps

# 2. Xem Nginx error log
docker compose logs nginx | grep error

# 3. Test kết nối từ Nginx đến backend
docker compose exec nginx wget -qO- http://backend:8080/health

# 4. Kiểm tra nginx.conf đúng upstream name
# upstream backend { server backend:8080; }
# Tên "backend" phải khớp service name trong compose

# 5. Reload Nginx config
docker compose exec nginx nginx -t  # Test config
docker compose exec nginx nginx -s reload
OOM Killed (Exit code 137) Memory +

Triệu chứng: Container bị kill đột ngột, exit code 137.

Nguyên nhân: Container vượt quá memory limit (hoặc host hết RAM).

Bash
# 1. Kiểm tra memory usage
docker stats --no-stream

# 2. Xem kernel OOM log
dmesg | grep -i oom | tail -20

# 3. Tăng memory limit trong compose
# deploy:
#   resources:
#     limits:
#       memory: 1G  # Tăng từ 512M lên 1G

# 4. Với Redis, set maxmemory
# command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
Docker Compose env vars không được đọc Config +

Triệu chứng: Container không nhận giá trị từ file .env.

Nguyên nhân phổ biến:

  • File .env không nằm cùng thư mục với docker-compose.yml
  • Có khoảng trắng quanh dấu = (sai: KEY = value)
  • Giá trị có ký tự đặc biệt nhưng không được quote
  • Compose đang đọc .env cũ (cached)
Bash
# 1. Verify env vars được truyền vào container
docker compose exec backend env | sort

# 2. Debug compose config (xem giá trị sau khi interpolate)
docker compose config

# 3. Force recreate (clear cache)
docker compose up -d --force-recreate

Performance Tuning

Khi hệ thống chạy chậm, kiểm tra theo thứ tự ưu tiên:

Bash
# 1. Kiểm tra resource usage
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"

# 2. Kiểm tra disk I/O
iostat -x 1 5

# 3. Kiểm tra PostgreSQL slow queries
docker compose exec postgres psql -U myapp_user -d myapp_db -c "
  SELECT pid, now() - pg_stat_activity.query_start AS duration, query
  FROM pg_stat_activity
  WHERE state != 'idle'
  ORDER BY duration DESC
  LIMIT 10;
"

# 4. Kiểm tra Redis memory usage
docker compose exec redis redis-cli -a $REDIS_PASSWORD INFO memory

# 5. Kiểm tra Nginx connection count
docker compose exec nginx sh -c "cat /proc/*/net/tcp | wc -l"
Trong hầu hết trường hợp, bottleneck nằm ở database queries (thiếu index, N+1 queries) hoặc thiếu RAM (PostgreSQL cần shared_buffers, Redis cần memory cho data). Kiểm tra hai điểm này trước khi tối ưu nơi khác.

Aliases hữu ích

Thêm vào ~/.bashrc hoặc ~/.zshrc để tiết kiệm thời gian:

Bash
# Docker Compose shortcuts
alias dc="docker compose"
alias dcu="docker compose up -d"
alias dcd="docker compose down"
alias dcl="docker compose logs -f"
alias dcp="docker compose ps"
alias dcr="docker compose restart"
alias dcb="docker compose build"

# Quick access
alias dc-api="docker compose exec backend bash"
alias dc-db="docker compose exec postgres psql -U myapp_user -d myapp_db"
alias dc-redis="docker compose exec redis redis-cli"

# Deploy shortcut
alias deploy="git pull && docker compose build && docker compose up -d"