docker debug 명령으로 컨테이너 및 이미지 디버깅 방법

DockerBeginner
지금 연습하기

소개

이 랩에서는 docker debug 명령과 기타 관련 기술을 사용하여 Docker 컨테이너 및 이미지를 효과적으로 디버깅하는 방법을 살펴봅니다. 셸이 없는 슬림 컨테이너를 디버깅하는 문제부터 시작하여, 컨테이너 환경 내에서 직접 명령을 실행하는 방법을 시연합니다.

그 다음, 컨테이너로 실행되기 전의 슬림 이미지를 직접 디버깅하는 방법을 배웁니다. 또한 디버깅 목적으로 실행 중인 컨테이너 내에서 파일을 수정하는 방법과 installuninstall 명령을 사용하여 디버그 툴박스를 관리하는 방법도 다룹니다. 마지막으로, entrypoint 명령을 활용하여 컨테이너 엔트리 포인트에 대한 더 깊은 이해를 얻을 것입니다.

셸이 없는 슬림 컨테이너 디버깅

이 단계에서는 셸이 설치되지 않은 슬림 컨테이너를 디버깅하는 방법을 배웁니다. 슬림 컨테이너는 이미지 크기와 공격 표면을 줄이기 위해 자주 사용되지만, 문제가 발생하면 디버깅하기 어려울 수 있습니다.

먼저, 메시지를 출력한 다음 종료되는 간단한 슬림 컨테이너를 실행해 보겠습니다. 매우 작은 Linux 배포판인 alpine 이미지를 사용합니다.

docker run alpine echo "Hello from Alpine!"

터미널에서 Hello from Alpine! 출력을 볼 수 있습니다. 이는 컨테이너가 성공적으로 실행되었음을 확인합니다.

이제 docker exec를 사용하여 이 컨테이너 내에서 명령을 실행해 보겠습니다. 일반적인 셸인 /bin/sh를 실행해 보겠습니다.

docker run -d --name slim-container alpine sleep 3600
docker exec -it slim-container /bin/sh

/bin/sh을 찾을 수 없다는 오류 메시지가 표시될 가능성이 높습니다. 이는 기본 구성에서 alpine 이미지가 bash 또는 sh와 같은 셸을 포함하지 않기 때문입니다. 이것은 슬림 컨테이너의 일반적인 특징입니다.

셸이 없는 컨테이너를 디버깅하려면 docker exec 명령을 사용하여 컨테이너 환경 내에서 특정 명령을 실행할 수 있습니다. 그러나 셸이 없으므로 명령을 직접 실행해야 합니다.

컨테이너의 루트 디렉터리에 있는 파일을 나열해 보겠습니다. ls 명령은 최소 환경에서도 일반적으로 사용할 수 있다는 것을 알고 있습니다.

docker exec -it slim-container ls /

bin, etc, lib 등과 같은 컨테이너 파일 시스템의 루트에 있는 디렉터리 및 파일 목록을 볼 수 있습니다. 이는 셸이 없더라도 컨테이너 내에서 직접 명령을 실행할 수 있음을 보여줍니다.

마지막으로, 생성한 컨테이너를 정리해 보겠습니다.

docker stop slim-container
docker rm slim-container

이 단계에서는 docker exec를 사용하여 명령을 직접 실행하여 셸이 없는 슬림 컨테이너와 상호 작용하는 방법을 보여주었습니다. 다음 단계에서는 다른 디버깅 기술을 살펴봅니다.

이미지 직접 디버깅 (슬림 이미지)

이전 단계에서는 실행 중인 슬림 컨테이너와 상호 작용하는 방법을 배웠습니다. 그러나 컨테이너로 실행하기 전에 슬림 이미지의 내용을 검사하거나 컨테이너가 시작되지 않는 경우도 있습니다. 이 단계에서는 슬림 이미지를 직접 디버깅하는 방법을 살펴봅니다.

Docker 는 이미지의 기본 엔트리 포인트와 명령을 재정의할 수 있는 기능을 갖춘 docker run 명령을 제공합니다. 이를 통해 이미지에서 생성된 임시 컨테이너 내에서 다른 명령을 실행하여 내용을 검사할 수 있습니다.

다시 alpine 이미지를 사용해 보겠습니다. 이는 슬림 이미지이며 기본적으로 셸이 없다는 것을 알고 있습니다. docker run을 사용하여 ls /와 같은 명령을 이미지에서 직접 실행할 수 있습니다.

docker run --rm alpine ls /

--rm 플래그는 명령이 완료된 후 임시 컨테이너가 자동으로 제거되도록 합니다. 이전 단계에서 실행 중인 컨테이너에서 ls /를 실행했을 때와 동일한 출력을 볼 수 있습니다. 이는 이미지의 파일 시스템을 직접 검사할 수 있음을 확인합니다.

이제 특정 명령이 이미지 내에 있는지 확인해 보겠습니다. 예를 들어, ping 명령이 있는지 확인해 보겠습니다.

docker run --rm alpine which ping

which: not found와 같은 오류 메시지가 표시될 가능성이 높습니다. 이는 ping 명령이 기본 alpine 이미지에 없음을 나타냅니다. 이것은 슬림 이미지의 또 다른 특징입니다. 슬림 이미지는 종종 필요한 최소한의 도구만 포함합니다.

cat과 같이 존재한다는 것을 알고 있는 명령을 시도해 보겠습니다.

docker run --rm alpine which cat

이번에는 /bin/cat 출력을 볼 수 있으며, 이는 cat 명령이 이미지에서 사용 가능하다는 것을 확인합니다.

docker run --rm <image> <command>를 사용하는 이 기술은 이미지의 내용을 빠르게 확인하고, 특정 파일 또는 명령의 존재를 확인하고, 장기간 실행되는 컨테이너를 실행하거나 새 이미지를 빌드할 필요 없이 이미지의 구조를 이해하는 데 매우 유용합니다.

실행 중인 컨테이너에서 파일 수정

이 단계에서는 실행 중인 컨테이너 내에서 파일을 수정하는 방법을 배웁니다. 이는 이미 실행 중인 컨테이너에 구성 파일을 변경하거나 임시 스크립트를 추가하는 등 디버깅 목적으로 유용할 수 있습니다.

alpine보다 기능이 풍부하고 셸과 일반 유틸리티를 포함하는 ubuntu 이미지를 기반으로 하는 간단한 컨테이너를 실행하는 것으로 시작합니다.

docker run -d --name my-ubuntu ubuntu sleep 3600

이 명령은 분리 모드 (-d) 로 Ubuntu 컨테이너를 실행하고 sleep 3600 명령을 사용하여 한 시간 동안 실행 상태를 유지합니다. 컨테이너를 쉽게 참조할 수 있도록 my-ubuntu로 이름을 지정했습니다.

이제 docker exec를 사용하여 실행 중인 컨테이너 내에서 셸을 얻어보겠습니다.

docker exec -it my-ubuntu /bin/bash

이제 my-ubuntu 컨테이너의 bash 셸 내에 있어야 합니다. 프롬프트가 변경되어 컨테이너 내에 있음을 나타냅니다.

컨테이너 내에서 /tmp 디렉터리에 새 파일을 만들어 보겠습니다.

echo "This is a test file." > /tmp/test_file.txt

이제 파일이 생성되었고 올바른 내용을 포함하는지 확인해 보겠습니다.

cat /tmp/test_file.txt

This is a test file. 출력을 볼 수 있습니다. 이는 실행 중인 컨테이너 내에서 파일을 생성하고 쓸 수 있었음을 확인합니다.

컨테이너의 셸을 종료하려면 exit를 입력하기만 하면 됩니다.

exit

이제 LabEx VM 터미널로 돌아왔습니다.

docker cp 명령을 사용하여 실행 중인 컨테이너 안팎으로 파일을 복사할 수도 있습니다. LabEx VM 에서 local_file.txt라는 파일을 만들고 컨테이너로 복사해 보겠습니다.

먼저, ~/project 디렉터리에 local_file.txt라는 파일을 만듭니다.

echo "This file is from the host." > ~/project/local_file.txt

이제 이 파일을 my-ubuntu 컨테이너의 /tmp 디렉터리로 복사합니다.

docker cp ~/project/local_file.txt my-ubuntu:/tmp/

docker cp의 형식은 docker cp <source_path> <container_name>:<destination_path> 또는 docker cp <container_name>:<source_path> <destination_path>입니다.

파일이 컨테이너로 복사되었는지 확인해 보겠습니다. 컨테이너의 셸로 다시 들어갑니다.

docker exec -it my-ubuntu /bin/bash

컨테이너 내에서 /tmplocal_file.txt가 있는지 확인합니다.

ls /tmp/

test_file.txt와 함께 local_file.txt가 나열되어 있는 것을 볼 수 있습니다.

이제 컨테이너 내에서 local_file.txt의 내용을 보겠습니다.

cat /tmp/local_file.txt

This file is from the host. 출력을 볼 수 있습니다.

다시 컨테이너의 셸을 종료합니다.

exit

마지막으로, 컨테이너를 정리해 보겠습니다.

docker stop my-ubuntu
docker rm my-ubuntu

이 단계에서는 셸을 얻기 위해 docker exec와 표준 Linux 명령을 사용하여 실행 중인 컨테이너 내에서 파일을 수정하는 방법과 docker cp를 사용하여 호스트와 컨테이너 간에 파일을 복사하는 방법을 보여주었습니다.

설치 및 제거를 통한 디버그 툴박스 관리

이 단계에서는 실행 중인 컨테이너 내에서 디버깅 도구를 추가하고 제거하는 방법을 살펴봅니다. 일반적으로 프로덕션 컨테이너 이미지를 최소한으로 유지하는 것이 권장되지만, 때로는 디버깅 목적으로 임시 도구를 설치해야 할 수 있습니다.

소프트웨어 설치를 쉽게 해주는 패키지 관리자 (apt) 가 있는 ubuntu 이미지를 다시 사용합니다.

먼저, 분리 모드로 새 Ubuntu 컨테이너를 실행해 보겠습니다.

docker run -d --name debug-ubuntu ubuntu sleep 3600

이제 컨테이너 내에서 셸을 얻어보겠습니다.

docker exec -it debug-ubuntu /bin/bash

컨테이너 내에서 기본적으로 설치되지 않은 ping과 같은 명령을 사용해 보겠습니다.

ping google.com

"command not found" 오류가 표시될 가능성이 높습니다.

ping 및 기타 네트워크 유틸리티를 설치하려면 apt 패키지 관리자를 사용할 수 있습니다. 먼저, 패키지 목록을 업데이트하는 것이 좋습니다.

apt update

이 명령은 저장소에서 사용 가능한 패키지에 대한 최신 정보를 가져옵니다.

이제 ping 명령을 제공하는 iputils-ping 패키지를 설치해 보겠습니다.

apt install -y iputils-ping

-y 플래그는 프롬프트 없이 설치를 자동으로 확인합니다.

설치가 완료되면 ping 명령을 사용할 수 있습니다.

ping -c 4 google.com

ping 명령의 출력을 볼 수 있으며, 이는 이제 컨테이너 내에서 사용 가능하고 작동함을 나타냅니다.

디버깅을 마치면 컨테이너를 깨끗하게 유지하고 새 이미지로 커밋하려는 경우 크기를 줄이기 위해 설치한 모든 도구를 제거하는 것이 좋습니다 (프로덕션을 위해 실행 중인 컨테이너를 수정하는 것은 일반적으로 권장되지 않음).

iputils-ping 패키지를 제거하려면 apt remove를 사용합니다.

apt remove -y iputils-ping

ping을 더 이상 사용할 수 없는지 확인할 수 있습니다.

ping google.com

다시 "command not found" 오류가 표시되어야 합니다.

컨테이너의 셸을 종료합니다.

exit

마지막으로, 컨테이너를 정리합니다.

docker stop debug-ubuntu
docker rm debug-ubuntu

이 단계에서는 패키지 관리자를 사용하여 실행 중인 컨테이너 내에서 디버깅 도구를 임시로 설치하고 제거하는 방법을 보여주었습니다. 이는 기본 이미지에 필요한 도구가 포함되어 있지 않은 컨테이너에서 문제를 해결하는 강력한 기술입니다.

entrypoint 명령어를 사용한 컨테이너 진입점 이해

이 단계에서는 Dockerfile 의 ENTRYPOINT 지시어와 컨테이너 실행 방식에 미치는 영향에 대해 배웁니다. ENTRYPOINT는 컨테이너가 시작될 때 실행될 명령을 정의합니다. 이는 종종 컨테이너의 주요 실행 파일을 설정하는 데 사용됩니다.

ENTRYPOINT를 사용하는 간단한 Dockerfile 을 만들어 보겠습니다. ~/project 디렉터리에서 다음 내용으로 Dockerfile이라는 파일을 만듭니다.

FROM alpine
ENTRYPOINT ["echo", "Hello from the entrypoint!"]
CMD ["default", "command"]

이 Dockerfile 은 alpine 이미지를 기본 이미지로 사용합니다. ENTRYPOINT["echo", "Hello from the entrypoint!"]로 설정됩니다. CMD["default", "command"]로 설정됩니다. ENTRYPOINTCMD가 모두 지정된 경우, CMD 인수는 ENTRYPOINT 명령에 인수로 전달됩니다.

이제 이 Dockerfile 에서 이미지를 빌드해 보겠습니다.

docker build -t my-entrypoint-image ~/project

이 명령은 ~/project 디렉터리의 Dockerfile 에서 my-entrypoint-image라는 이미지를 빌드합니다.

이제 추가 명령을 제공하지 않고 이 이미지에서 컨테이너를 실행해 보겠습니다.

docker run my-entrypoint-image

Hello from the entrypoint! default command 출력을 볼 수 있습니다. 이는 ENTRYPOINT 명령 (echo) 이 실행되었고 CMD 인수 (default command) 가 해당 명령으로 전달되었음을 보여줍니다.

이제 컨테이너를 실행하고 docker run 줄에서 다른 명령을 제공해 보겠습니다. docker run 줄에서 명령을 제공하면 Dockerfile 의 CMD 지시어가 재정의되지만, ENTRYPOINT는 제공된 명령을 인수로 사용하여 계속 실행됩니다.

docker run my-entrypoint-image "override command"

Hello from the entrypoint! override command 출력을 볼 수 있습니다. 이는 ENTRYPOINT가 계속 실행되었지만 docker run 명령의 인수 (override command) 가 CMD 인수를 대체했음을 보여줍니다.

ENTRYPOINT를 완전히 무시하고 다른 명령을 실행하려면 어떻게 해야 할까요? docker run과 함께 --entrypoint 플래그를 사용할 수 있습니다.

docker run --entrypoint /bin/echo my-entrypoint-image "Running a different command"

Running a different command 출력을 볼 수 있습니다. 이 경우 --entrypoint 플래그는 Dockerfile 에 지정된 ENTRYPOINT를 재정의했으며, 제공된 명령 (/bin/echo) 이 인수 (Running a different command) 와 함께 실행되었습니다.

ENTRYPOINTCMD를 이해하는 것은 Docker 이미지를 빌드하고 디버깅하는 데 매우 중요합니다. ENTRYPOINT는 핵심 실행 파일을 정의하고, CMD는 해당 실행 파일에 대한 기본 인수를 제공하거나 ENTRYPOINT가 설정되지 않은 경우 기본 명령을 제공합니다.

요약

이 랩에서는 docker debug 명령 및 관련 기술을 사용하여 Docker 컨테이너 및 이미지를 디버깅하는 방법을 배웠습니다. 셸이 없는 슬림 컨테이너를 디버깅하는 방법을 탐구하는 것으로 시작하여, bash 또는 sh와 같은 전통적인 셸이 없더라도 docker exec를 사용하여 컨테이너 환경 내에서 직접 명령을 실행할 수 있음을 시연했습니다. 이는 최소 컨테이너 이미지를 문제 해결하는 데 중요한 기술입니다.

제공된 내용은 첫 번째 단계만 다루지만, 랩의 전체 구조는 후속 단계에서 슬림 이미지를 직접 디버깅하고, 실행 중인 컨테이너 내에서 파일을 수정하고, install 및 uninstall 명령으로 디버그 툴박스를 관리하고, entrypoint 명령을 사용하여 컨테이너 진입점을 이해하는 방법을 자세히 다룰 것임을 나타냅니다. 이러한 단계는 Docker 화된 애플리케이션 및 이미지 내에서 문제를 진단하고 해결하는 능력을 더욱 향상시킬 것입니다.