Docker
Docker 컨테이너가 서버에서만 실패할 때
로컬에서는 정상 작동하는 Docker 컨테이너가 서버 배포 후 에러를 일으킬 때 로그를 읽고 원인을 찾는 방법.
Docker를 로컬에서 빌드해서 서버에서 실행하면, 예상치 못한 환경 차이가 드러난다. 로그 없이는 무엇이 문제인지 알 수 없다.
컨테이너 로그 확인
가장 먼저 할 일은 컨테이너가 왜 멈췄는지 보는 것이다:
# 실행 중인 컨테이너 목록
docker ps
# 최근 출력된 로그 (마지막 100줄)
docker logs --tail=100 container-name
# 실시간으로 로그 보기
docker logs -f container-name
에러 메시지가 명확하다면 거기서부터 시작한다.
컨테이너 실행 상태 검사
컨테이너가 실행 중이나 계속 재시작되는가?
# 컨테이너 상세 정보
docker inspect container-name
# State.Running: true인가?
# State.ExitCode가 0이 아니면 비정상 종료
만약 컨테이너가 계속 재시작된다면 시작 커맨드에서 문제가 생기는 것이다.
환경 변수 확인
Dockerfile이나 docker-compose에서 정의한 환경 변수가 실제로 전달되었나?
# 컨테이너 내부에 진입해서 환경 변수 확인
docker exec container-name env | grep YOUR_VAR
# 환경 변수가 없다면 docker run이나 docker-compose.yml에서 확인
특히 데이터베이스 접속 정보나 API 키 같은 중요 환경 변수를 확인한다.
포트 바인딩
Dockerfile의 EXPOSE와 실제 포트 매핑이 일치하나?
# 컨테이너가 어느 포트에서 listen 중인가?
netstat -tlnp | grep container-pid
# 호스트의 포트 매핑 확인
docker port container-name
예를 들어 Dockerfile에서 EXPOSE 8080이지만, 스크립트에서는 5000으로 실행 중이면 문제가 생긴다.
네트워크와 DNS
Docker 네트워크 설정이 서버에서 다를 수 있다:
# 컨테이너 내부에서 외부 서비스 접근 테스트
docker exec container-name curl https://api.example.com
# DNS 해석 확인
docker exec container-name nslookup example.com
로컬 PC에서는 DNS가 잘 작동하지만, 서버 환경에서 DNS 설정이 없을 수 있다.
볼륨과 파일 시스템
volume 마운트를 사용한다면 서버에서 그 경로가 존재하나?
# 컨테이너가 마운트한 경로 확인
docker inspect container-name | grep Mounts -A 10
# 호스트의 해당 경로가 존재하고 권한은?
ls -la /path/to/volume
로컬에서는 ./data:/app/data 경로가 있지만, 서버에 ./data 디렉토리가 없으면 마운트가 실패한다.
이미지 태그와 버전
로컬에서는 최신 이미지로 빌드했지만, 서버에서는 오래된 버전을 사용하고 있지는 않나?
# 현재 실행 중인 이미지 확인
docker ps --no-trunc | grep container-name
# 이미지 ID와 태그 확인
docker images
배포 파이프라인에서 올바른 버전의 이미지를 배포하고 있는지 확인한다.
컨테이너 직접 실행해보기
서버에서 직접 컨테이너를 실행해본다:
# 로컬과 같은 방식으로 실행
docker run -it -e VAR=value -p 8080:8080 image-name
그러면 로그가 터미널에 바로 나타나고, 무엇이 문제인지 명확해진다.