2025/11 8

컨테이너 포트를 host 포트로 못 쓰면???

hostPort를 못 쓰는 이유는 보통 1) 보안 정책 2) 포트 점유 방지 3) 여러 컨테이너가 동일 포트를 써야 하는 구조 때문임 근데 실제 운영에서는 hostPort 없이도 대부분 해결 가능함. 1) ports: “컨테이너포트:랜덤호스트포트” 형태로 노출hostPort를 고정으로 쓰지 못해도Docker는 자동으로 사용 가능한 포트를 매핑해줌. ports: - "0:3000" # 호스트 포트를 0으로 주면 자동 할당 2) Reverse Proxy(Nginx / Traefik) 앞단에서 처리hostPort를 못 써도컨테이너들은 내부 포트만 열어두면 되고,외부 노출은 프록시 하나만 담당하면 됨.컨테이너들은 포트 공유 가능 (예: 모두 3000 이용)→ Nginx/Traefik이 호스트에 포트 ..

TIL 2025.11.28

컨테이너 Exit 원인 명령어 정리

도커 컨테이너 죽으면 Exit Code 하나로 대충 원인 유추 가능함운영하면서 제일 많이 본 코드들 정리함 Exit 137 (제일 자주 나옴)SIGKILL(9) 받았다는 뜻임원인 두 가지밖에 없음헬스체크 실패 → Swarm/K8s가 강제 killOOM(메모리 부족) → 커널이 kill공통점: 둘 다 강제 종료라 137로 뜸운영에서 spike 나면 대부분 이거 뜸 Exit 143 (정상 종료)SIGTERM(15) 받았다는 뜻docker stop, rolling update 때 자주 뜸정상 종료라 문제 아님업데이트나 재배포 시 거의 무조건 143 찍힘 !! Exit 1 (앱 내부 오류)Generic error내부 코드 예외, 설정 파일 오류, DB 연결 실패, 포트 충돌 등Node.js에서 thr..

TIL 2025.11.28

Nginx 502 Bad Gateway 발생 원인 정리

502는 보통 Nginx → Backend(업스트림) 사이에서 통신이 안 될 때 뜨는 에러임.즉, Nginx 자체 문제라기보다는 뒤에 있는 서버/컨테이너가 제대로 응답을 못 줬다는 신호임. 업스트림 서버(백엔드) 자체가 죽어있는 경우Nginx는 살아있는데, API / Socket 서버가 다운됨Docker라면 컨테이너 stop 상태PM2/Node라면 프로세스 죽어있음Nginx 입장에서 뒤 서버가 아예 없으니까 502 발생함 확인 방법 docker ps pm2 status systemctl status backend 업스트림 포트가 열려있지 않음Nginx는 http://api:3000으로 보내는데백엔드는 실제로 3000이 아니라 다른 포트에서 떠있는 경우또는 방화벽 / 보안 정책으로 포트가 막혀있음확인 방..

TIL 2025.11.26

redis 남아있는 죽은 socket.id 정리하기.

소켓 서버 운영하다 보면 Redis에 저장된 socket.id랑실제 소켓 서버가 가진 socket.id가 불일치하는 경우 종종 생김.브라우저 강제 종료, 네트워크 끊김, 모바일 전환 등에서 흔하게 발생함. 이럴 때 무조건 Redis 전체를 정리하는 방식은 비효율적임.그래서 발견되는 순간에만 제거하는 lazy-clean 방식 적용함. 🔍 정리 조건 Redis에 저장된 sid가 실제 소켓 서버에 없으면 정리함. if (!io.sockets.sockets.has(sid)) { client.srem(`${tenant}:${user}:socket`, sid)} 🔧 장점쓸데없는 전체 스캔 없음정상 동작 중인 유저에게 부담 없음자연스럽게 “좀비 socket.id”만 제거됨Redis와 socket 서버 사..

TIL 2025.11.24

proxy_temp 파일이 날뛰어서 디스크 꽉 찼던 사건 정리

최근에 서버 디스크가 갑자기 꽉 차는 이슈가 있었음.처음엔 “누가 또 큰 파일 던졌나?” 싶었는데 확인해보니 proxy_temp 디렉토리가 범인이었음. 🔍 원래 proxy_temp가 어떤 역할이냐면클라이언트에게 파일 전송할 때 nginx가 임시로 파일을 저장하는 곳임다운로드가 끝나면 바로 삭제되는 게 정상임즉, 보통 여기에 오래 남는 파일은 없어야 함 ❗ 그런데 이번엔 비정상 상황 발생함다운로드가 중간에 끊기거나nginx worker가 파일 FD(파일 디스크립터)를 놓지 않는 상태가 됐던 듯함즉, FD 누수(File Descriptor leak) 발생했음그래서 삭제가 안 되고 계속 쌓임 📌 실제로 어떤 일이 벌어졌나proxy_temp 아래에 70MB짜리 파일이 수십 개씩 생김심지어 삭제된 걸로 보..

TIL 2025.11.18

서버 CPU 픽 떠서 서버 에러율 높았던 사건 회고록

최근에 갑자기 DB CPU나 WAS CPU가 이유 없이 치솟는 일이 종종 있었음.트래픽도 같이 비정상적으로 높아져서 살짝 당황함.‘우리 서비스가 DDOS 맞을 정도로 유명하진 않을텐데…?’의문 들면서 로그 타임라인 맞춰서 살펴봄. 그랬더니 그 시간대에 docker 컨테이너가 꺼졌다가 다시 켜진 흔적이 있었음.여기서부터 느낌이 옴: 뭔가 서버가 죽어서 재시작됐구나.조금 더 뒤져보니 문제의 원인은 의외로 단순했음. chat_uid 중복 → 예외처리 실패 → await 안 걸림 → Promise 터짐chat_uid가 중복으로 들어오는 특정 케이스가 있었음예외처리가 잘못되어 있어서try/catch로 감싸도await 누락된 비동기 부분에서 Promise rejection이 튀어나와버림결국 노드 프로세스가 제대..

TIL 2025.11.17

Redis 한쪽노드에 메모리 몰린 경우

Redis 클러스터에서 {}(해시태그) 쓰면 생기는 일 정리함👇 🧩 해시태그의 의미Redis Cluster는 키를 16384개의 슬롯(slot)으로 나눠서 저장함.슬롯들은 여러 노드에 분배되어 부하 분산됨.그런데 키에 {} 가 있으면 이야기가 달라짐.{} 안의 문자열만 해시 계산에 사용됨.즉 {} 안에 같은 문자열이 있으면 → 전부 같은 슬롯 → 같은 노드에 저장됨 ✅ 🔍 예시키해시 계산 기준결과bull:fcmQueue:123전체 문자열슬롯 다르게 → 여러 노드로 분산bull:{fcmQueue}:123{fcmQueue} 부분만전부 같은 슬롯 → 한 노드로 몰림 ✅즉 bull:{fcmQueue}:fcmQueue:* 이런 형태면모두 {fcmQueue} 기준으로 같은 슬롯 배정 →클러스터의 한 마스터..

TIL 2025.11.03

Redis keys vs Scan 차이

운영 Redis에서 KEYS 썼다가 서버 멈추는 경우 많음결과는 SCAN이랑 비슷해 보여도 성능 차이는 극명함 🔹 1. KEYS — 전체 탐색 (Blocking 방식) redis-cli KEYS "pattern" 모든 키 한 번에 전부 스캔함Blocking 방식이라 Redis가 키 전부 메모리에 올릴 때까지 대기함키 수 많으면 서버 응답 멈춘 듯 보임CPU, 메모리 급상승Redis는 단일 스레드 → 그동안 다른 명령 대기수십만 개 이상이면 진짜 위험함👉 개발/테스트에서는 OK, 운영에서는 절대 금지 🔹 2. SCAN — 점진적 비차단 스캔 (Cursor 기반) redis-cli --scan --pattern "pattern" Cursor 기반 반복 탐색한 번에 일부 키만 반환, 나머지는 다음 호..

TIL 2025.11.02