Docker Hardened Image에 sh가 없다면, 빌드와 디버깅은 어떻게 할까?

앱은 잘 도는데 컨테이너에 들어가려 하자 sh를 찾을 수 없다는 오류가 뜬다. 셸도 패키지 관리자도 없는 이미지에서 빌드와 점검은 어떻게 할까?

Docker Hardened Image에 sh가 없다면, 빌드와 디버깅은 어떻게 할까?
세 줄 요약
  • DHI 런타임에서 sh·apt·apk가 없는 것은 최소화된 이미지의 설계에 따른다.
  • 셸과 설치 도구가 필요한 빌드에는 dev 변형을 쓰고, 최종 실행 이미지에는 필요한 결과물을 복사한다.
  • Docker Debug로 셸 없이 만든 컨테이너를 살필 수 있지만, 실행 중 컨테이너의 파일을 고치면 실제로 반영된다.

런타임에 셸이 없으면 docker exec로 셸을 만들 수는 없다

Docker Hardened Images(DHI)의 런타임 변형은 sh·bash와 패키지 매니저를 제외한다. docker exec -it myapp sh를 실행했을 때 프로그램을 찾을 수 없다는 오류가 나면 선택한 이미지의 변형부터 봐야 한다. 컨테이너가 고장 났다는 뜻으로 단정할 상황은 아니다.

Docker의 문제 해결 문서는 이 경우를 별도로 설명한다. 셸과 패키지 도구가 필요한 작업에는 -dev 변형을 쓰고, 이미 실행 중인 최소 이미지의 내부를 살필 때는 Docker Debug를 사용한다. 두 방식은 해결하는 단계가 다르다.

DHI에는 무료 Community 제공 범위가 있지만, 무료로 받을 수 있다는 사실이 기존 Dockerfile의 모든 가정을 유지한다는 뜻은 아니다. 어떤 도구가 어디에 필요한지를 나누는 것이 전환의 출발점이다.

apt와 apk는 최종 런타임보다 앞에서 사용한다

기존 Dockerfile이 패키지를 설치하고 컴파일한 뒤 같은 이미지로 서비스를 시작했다면 빌드와 실행 단계를 나눌 수 있다. 공식 이전 가이드는 빌드에는 dev 또는 sdk 태그를, 마지막 단계에는 런타임 이미지를 권장한다.

필요한 작업사용할 환경최종 이미지로 넘길 것
셸 명령·패키지 설치·컴파일도구가 있는 dev/sdk 빌드 단계앱과 실행에 필요한 의존성이다.
서비스 실행런타임 변형빌드 도구 전체를 넣을 필요는 없다.
개발 중 셸로 원인 파악dev 변형으로 만든 개발 컨테이너검사 도구를 운영 이미지의 기본 구성으로 옮기지 않는다.

Debian 계열을 쓰던 앱은 Debian 기반 DHI로, Alpine 계열은 Alpine 기반 DHI로 옮기는 것이 공식 가이드의 출발점이다. 패키지 관리와 의존성 차이를 줄이기 위한 선택이다. 빌드 결과 파일만 복사했다고 모든 실행 의존성까지 갖춰지는 것은 아니므로, 앱이 실제로 필요로 하는 파일을 포함해야 한다.

이미지를 받기 전에는 docker login dhi.io로 인증한다. DHI는 latest 태그를 제공하지 않으므로 카탈로그에서 언어 버전과 배포판에 맞는 태그를 고른다. 셸 명령을 런타임 단계에 그대로 남겨 둔 채 FROM 주소만 바꾸면 도구 부재 문제는 해결되지 않는다.

Docker Debug는 도구를 가져오지만, 실행 파일 수정까지 차단하지는 않는다

Docker Debug를 사용할 수 있는 환경에서는 기존 컨테이너 이름을 대상으로 다음 명령을 실행한다. myapp은 실제 검사할 컨테이너 이름으로 바꾼다.

docker debug myapp

공식 CLI 설명에 따르면 대상 이미지에 셸이 없어도 Debug가 자체 도구 모음을 제공한다. 원본 이미지를 다시 만들지 않고 파일과 프로세스를 살피거나 시작 명령을 조사할 수 있다. 도구 모음 안의 install로 추가한 패키지는 검사 도구 쪽에 들어간다.

대상의 상태에 따라 변경 효과는 다르다. 이미지나 정지된 컨테이너를 열었을 때의 변경은 셸을 나가면 버려진다. 실행 중이거나 일시 정지된 컨테이너의 파일을 수정하면 그 변경은 해당 컨테이너에 바로 보인다. 원본 이미지를 바꾸지 않는다는 설명과 실행 서비스의 파일을 바꾸지 않는다는 설명을 혼동하면 안 된다.

Docker Desktop은 4.49.0 릴리스부터 Debug를 모든 사용자에게 무료로 제공한다고 명시했다. 다만 Engine과 CLI만 설치한 서버에 같은 명령이 들어 있다고 가정해서는 안 된다. 개발용 셸이 필요한 경우 공식 문서의 dhi.io/python:3.13-dev 같은 dev 변형도 선택지가 된다.

셸 문제를 해결한 뒤에는 파일 권한과 시작 명령을 맞춘다

런타임 DHI는 기본적으로 nonroot 사용자로 실행된다. 이전 체크리스트에 따라 앱 파일을 읽을 수 있는지, 필요한 작업 디렉터리에 쓸 수 있는지를 확인해야 한다. 선택한 이미지의 사용자와 파일 소유권을 대조하는 작업이다.

기존 이미지와 ENTRYPOINT 또는 CMD도 다를 수 있다. 이미지 문서나 docker inspect로 실제 시작 명령을 읽고, 앱의 시작 방식이 그 설정에 맞는지 확인한다. 특히 셸 스크립트를 실행 전제로 삼았다면 최종 이미지에 필요한 실행기가 있는지 살펴야 한다.

DHI 전환에서 셸이 없다는 문제의 답은 작업 위치에 있다. 설치와 컴파일은 빌드 단계에서 끝내고, 서비스는 런타임에서 실행하며, 내부를 살피는 도구는 Debug나 개발용 변형에서 준비한다.