Docker
Docker 이미지 배포 후 문제가 생겼을 때
컨테이너 배포 후 앱이 안 되면, 먼저 컨테이너가 실제로 시작됐는지, 로그에 에러가 있는지 확인해야 한다.
Docker 배포 후 문제가 생기면 어디를 봐야 할지 모를 수 있다. 컨테이너 내부인지, 네트워크인지, 설정인지 원인 범위가 넓기 때문이다. 하지만 순서대로 확인하면 빨리 찾을 수 있다.
컨테이너 상태부터 확인하기
먼저 컨테이너가 실제로 실행 중인지 본다.
# 실행 중인 컨테이너 목록
docker ps
# 내 앱의 컨테이너 찾기
docker ps | grep my-app
# 컨테이너 상태가 "Up"이 아니면?
docker inspect my-app-container | grep -A 5 State
Status가 "Exited"라면 컨테이너가 시작했다가 바로 종료됐다는 뜻이다. 로그를 봐야 한다.
컨테이너 로그 확인하기
# 최근 100줄 로그
docker logs --tail=100 my-app-container
# 에러만 필터링
docker logs my-app-container 2>&1 | grep -i 'error\|failed\|exception'
# 실시간 로그 스트리밍
docker logs -f my-app-container
로그에서 다음을 찾아본다:
- "PORT already in use": 포트 충돌
- "Connection refused": 데이터베이스 연결 실패
- "No such file or directory": 파일 누락
- "permission denied": 권한 문제
환경 변수와 마운트 확인하기
로컬에선 잘되는데 컨테이너에서 안 될 때는 보통 환경 설정의 차이 때문이다.
# 컨테이너의 환경 변수
docker exec my-app-container env | grep -i 'db\|api\|secret'
# 마운트된 볼륨 확인
docker inspect my-app-container | grep -A 10 Mounts
# 실제 파일이 있는지 확인
docker exec my-app-container ls -la /app/config/
Dockerfile에서 COPY 명령으로 파일을 복사했는데, 빌드 시에 파일이 없으면 이미지 안에도 없다.
포트와 네트워크 확인하기
# 컨테이너가 어느 포트를 열고 있는가
docker inspect my-app-container | grep ExposedPorts
# 호스트의 포트 바인딩
docker port my-app-container
# 포트가 실제로 열려 있는가
curl http://localhost:3000/health
Dockerfile에는 EXPOSE 8080이라고 했는데, 실제론 3000에서 리스닝하고 있을 수도 있다. docker run 시 포트 매핑을 -p 8080:3000으로 해야 한다.
한 가지씩 수정하고 다시 빌드하기
문제를 찾았다면 Dockerfile이나 설정을 수정하고 다시 빌드한다.
# 이미지 다시 빌드
docker build -t my-app:v2 .
# 기존 컨테이너 중지
docker stop my-app-container
# 기존 컨테이너 삭제
docker rm my-app-container
# 새 이미지로 실행
docker run -d --name my-app-container my-app:v2
# 잘 되는지 확인
docker logs my-app-container
이렇게 한 번에 한 가지씩 수정해야 뭐가 효과가 있었는지 알 수 있다.
전과 후 비교하기
수정 전후의 이미지를 비교해서 뭐가 바뀌었는지 본다.
# 이미지 레이어 확인
docker history my-app:v1
docker history my-app:v2
# 이미지 크기 비교
docker images | grep my-app
이미지 크기가 크게 달라졌다면, 불필요한 파일이 많이 복사되고 있을 수 있다. .dockerignore 파일로 제외할 수 있다.
배포 후 안정성 확인
# 컨테이너 재시작 정책이 있는가?
docker inspect my-app-container | grep RestartPolicy
# CPU와 메모리 제한이 적절한가?
docker stats my-app-container
컨테이너가 자동으로 재시작되도록 --restart=always를 주고, 메모리가 제한을 넘으면 OOMKilled되지 않도록 -m 512m 같은 설정을 해준다.