컨테이너 심층 탐구

DockerBeginner
지금 연습하기

소개

Docker 컨테이너는 현대적인 애플리케이션 배포의 핵심 구성 요소입니다. 이번 실습에서는 Docker 의 기능을 더 깊이 이해할 수 있도록 고급 컨테이너 관리 기술을 살펴봅니다. 다양한 모드로 컨테이너를 실행하는 방법, 컨테이너의 생명주기 관리, 상세 정보 확인, 로그 활용, 컨테이너 내부에서의 명령 실행, 파일 복사, 환경 변수 설정, 그리고 컨테이너 리소스 제한 방법 등을 다룹니다. 이 과정을 마치면 Docker 컨테이너를 효과적으로 다루는 데 필요한 포괄적인 지식을 갖추게 될 것입니다.

다양한 모드로 컨테이너 실행하기

Docker 는 다양한 사용 사례에 맞춰 컨테이너를 서로 다른 모드로 실행할 수 있게 해줍니다. 여기서는 가장 흔히 쓰이는 두 가지 모드인 백그라운드 모드 (Detached mode) 와 대화형 모드 (Interactive mode) 를 살펴보겠습니다.

먼저, 백그라운드 모드로 컨테이너를 실행해 보겠습니다.

docker run -d --name nginx-detached nginx

이 명령은 다음과 같은 역할을 합니다:

  • -d: 컨테이너를 백그라운드 (Detached mode) 에서 실행합니다.
  • --name nginx-detached: 컨테이너에 "nginx-detached"라는 이름을 부여합니다.
  • nginx: 사용할 이미지를 지정합니다. (로컬에 없으면 Docker Hub 에서 자동으로 내려받습니다.)

명령을 실행하면 컨테이너 ID 를 나타내는 긴 문자열이 출력됩니다.

다음 명령으로 컨테이너의 상태를 확인할 수 있습니다.

docker ps

이번에는 대화형 모드로 컨테이너를 실행해 보겠습니다.

docker run -it --name ubuntu-interactive ubuntu /bin/bash

이 명령은 다음과 같은 역할을 합니다:

  • -it: 가상 터미널 (pseudo-TTY) 을 통해 컨테이너와 상호작용할 수 있는 모드로 실행합니다.
  • --name ubuntu-interactive: 컨테이너 이름을 "ubuntu-interactive"로 설정합니다.
  • ubuntu: 사용할 이미지를 지정합니다.
  • /bin/bash: 컨테이너 내부에서 실행할 명령입니다. (여기서는 bash 셸을 실행합니다.)

이제 Ubuntu 컨테이너 내부에 접속된 상태가 됩니다. 컨테이너에서 나가려면 exit를 입력하세요.

현재 실행 중인 컨테이너 목록을 확인해 봅시다.

docker ps

nginx-detached 컨테이너는 계속 실행 중이지만, ubuntu-interactive 컨테이너는 종료했기 때문에 목록에 보이지 않을 것입니다.

컨테이너 생명주기 관리하기

컨테이너를 시작, 중지, 재시작하는 방법을 이해하는 것은 효율적인 컨테이너 관리를 위해 매우 중요합니다.

우선 실행 중인 nginx-detached 컨테이너를 중지해 보겠습니다.

docker stop nginx-detached

이제 컨테이너들의 상태를 확인해 봅시다.

docker ps -a

nginx-detached 컨테이너의 상태가 "Exited"로 바뀐 것을 확인할 수 있습니다.

다시 시작해 보겠습니다.

docker start nginx-detached

상태를 다시 확인합니다.

docker ps

이제 nginx-detached 컨테이너가 다시 "Up" 상태가 되었습니다.

실행 중인 컨테이너를 재시작할 수도 있습니다.

docker restart nginx-detached

중지된 컨테이너를 포함하여 현재 모든 컨테이너의 상태를 보려면 다음 명령을 사용합니다.

docker ps -a

목록에서 nginx-detachedubuntu-interactive 컨테이너의 현재 상태를 모두 볼 수 있습니다.

이제 중지된 상태인 ubuntu-interactive 컨테이너를 삭제해 보겠습니다.

docker rm ubuntu-interactive

삭제가 잘 되었는지 확인합니다.

docker ps -a

목록에서 ubuntu-interactive 컨테이너가 사라진 것을 확인할 수 있습니다.

컨테이너 상세 정보 검사하기

Docker 는 컨테이너의 세부 정보를 파악할 수 있는 강력한 도구를 제공합니다.

컨테이너에 대한 상세한 정보를 얻으려면 inspect 명령을 사용합니다.

docker inspect nginx-detached

이 명령은 컨테이너의 모든 정보를 JSON 배열 형태로 출력합니다. 내용이 너무 방대하므로 필터를 사용하여 특정 정보만 골라내 보겠습니다.

컨테이너의 IP 주소만 확인하려면 다음과 같이 입력합니다.

docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx-detached

컨테이너의 현재 상태만 확인하려면 다음과 같이 입력합니다.

docker inspect -f '{{.State.Status}}' nginx-detached

이 명령들은 Go 템플릿을 사용하여 출력을 필터링합니다. -f 플래그를 통해 원하는 형식을 지정할 수 있습니다.

포트 매핑 정보도 확인해 봅시다.

docker port nginx-detached

포트 매핑은 컨테이너가 호스트 시스템이나 외부 네트워크와 통신할 수 있게 해줍니다. 호스트 시스템의 특정 포트를 컨테이너 내부의 포트와 연결하는 방식입니다. 이는 Docker 환경 외부에서 컨테이너 내부의 서비스에 접속할 때 필수적입니다.

매핑된 포트가 없다면 이 명령은 아무것도 출력하지 않습니다. 현재 nginx-detached 컨테이너는 명시적으로 포트를 매핑하지 않았으므로 출력이 없을 것입니다.

포트 매핑을 직접 확인해 보기 위해, 포트 설정이 포함된 새로운 Nginx 컨테이너를 생성해 보겠습니다.

docker run -d --name nginx-with-port -p 8080:80 nginx

이 명령은 호스트의 8080 포트를 컨테이너의 80 포트로 연결합니다. 이제 포트 매핑을 다시 확인해 봅니다.

docker port nginx-with-port

다음과 유사한 출력이 나타날 것입니다.

80/tcp -> 0.0.0.0:8080

이는 호스트 머신의 8080 포트로 들어오는 트래픽이 Nginx 가 대기 중인 컨테이너의 80 포트로 전달됨을 의미합니다.

컨테이너 로그 작업하기

컨테이너 로그를 확인하고 이해하는 것은 애플리케이션의 문제를 해결하고 모니터링하는 데 매우 중요합니다.

실행 중인 nginx 컨테이너의 로그를 확인해 봅시다.

docker logs nginx-detached

이 명령은 컨테이너가 시작된 시점부터의 모든 로그를 보여줍니다. 가장 최근의 로그만 보려면 --tail 옵션을 사용합니다.

docker logs --tail 10 nginx-detached

마지막 10 줄의 로그만 출력됩니다.

로그를 실시간으로 계속 확인하려면 (마치 tail -f처럼) -f 옵션을 사용합니다.

docker logs -f nginx-detached

새로운 로그가 생성될 때마다 화면에 실시간으로 출력됩니다. 로그 확인을 마치려면 Ctrl+C를 누르세요.

로그에 타임스탬프를 추가하여 볼 수도 있습니다.

docker logs --timestamps nginx-detached

이 기능은 시간대별로 발생한 문제를 디버깅할 때 특히 유용합니다.

실행 중인 컨테이너에서 명령 실행하기

Docker 를 사용하면 실행 중인 컨테이너 내부에서 직접 명령을 실행할 수 있습니다. 이는 디버깅이나 유지보수 작업 시 매우 유용합니다.

먼저 nginx 컨테이너에서 간단한 명령을 실행해 보겠습니다.

docker exec nginx-detached echo "Hello from inside the container"

터미널에 "Hello from inside the container"라는 문구가 출력되는 것을 볼 수 있습니다.

이번에는 컨테이너 내부의 대화형 셸에 접속해 보겠습니다.

docker exec -it nginx-detached /bin/bash

이제 컨테이너 내부로 들어왔습니다. 내부를 조금 살펴봅시다.

ls /etc/nginx
cat /etc/nginx/nginx.conf
exit

이 명령들은 Nginx 설정 디렉토리의 내용을 나열하고 기본 설정 파일을 확인합니다. exit 명령을 입력하면 다시 호스트 시스템의 셸로 돌아옵니다.

컨테이너와 파일 주고받기

Docker 는 호스트 시스템과 컨테이너 간에 파일을 복사하는 방법을 제공합니다. 설정 파일을 업데이트하거나 로그 파일을 추출할 때 유용합니다.

먼저 호스트 시스템에 간단한 HTML 파일을 하나 만듭니다.

echo "<html><body><h1>Hello from host</h1></body></html>" > hello.html

이제 이 파일을 nginx 컨테이너 내부로 복사해 보겠습니다.

docker cp hello.html nginx-detached:/usr/share/nginx/html/hello.html

파일이 잘 복사되었는지 컨테이너 내 명령 실행을 통해 확인합니다.

docker exec nginx-detached cat /usr/share/nginx/html/hello.html

작성했던 HTML 파일의 내용이 출력될 것입니다.

반대로 컨테이너에 있는 파일을 호스트로 가져와 보겠습니다.

docker cp nginx-detached:/etc/nginx/nginx.conf ~/project/nginx.conf

컨테이너의 Nginx 설정 파일을 호스트의 현재 프로젝트 디렉토리로 복사했습니다.

파일이 잘 복사되었는지 확인합니다.

ls -l ~/project/nginx.conf

목록에 nginx.conf 파일이 보이는 것을 확인할 수 있습니다.

컨테이너 환경 변수 설정하기

환경 변수는 컨테이너에서 실행되는 애플리케이션을 설정하는 핵심적인 방법입니다. 환경 변수를 설정하고 사용하는 방법을 알아봅시다.

먼저 환경 변수를 지정하여 새 컨테이너를 실행해 보겠습니다.

docker run --name env-test -e MY_VAR="Hello, Environment" -d ubuntu sleep infinity

이 명령은 다음과 같은 역할을 합니다:

  • --name env-test: 컨테이너 이름을 "env-test"로 지정합니다.
  • -e MY_VAR="Hello, Environment": MY_VAR 라는 이름의 환경 변수를 설정합니다.
  • -d: 백그라운드에서 실행합니다.
  • ubuntu: Ubuntu 이미지를 사용합니다.
  • sleep infinity: 컨테이너가 종료되지 않고 계속 실행되도록 유지합니다.

이제 환경 변수가 제대로 설정되었는지 확인해 봅시다.

docker exec env-test env | grep MY_VAR

출력 결과에서 MY_VAR=Hello, Environment를 확인할 수 있습니다.

파일을 사용하여 여러 환경 변수를 한꺼번에 설정할 수도 있습니다. env_file이라는 이름의 파일을 만들고 다음 내용을 입력하세요.

nano 나 vim 편집기를 사용하여 파일을 생성합니다.

nano env_file
ANOTHER_VAR=From a file
YET_ANOTHER_VAR=Also from the file

편집기에서 Ctrl+X, Y, Enter를 차례로 눌러 저장하고 나옵니다.

이제 이 파일을 사용하여 다른 컨테이너를 실행해 봅니다.

docker run --name env-file-test --env-file env_file -d ubuntu sleep infinity

새 컨테이너의 환경 변수를 확인합니다.

docker exec env-file-test env | grep -E "ANOTHER_VAR|YET_ANOTHER_VAR"

파일에 정의했던 두 변수가 모두 출력되는 것을 볼 수 있습니다.

컨테이너 리소스 제한하기

Docker 를 사용하면 컨테이너가 사용할 수 있는 리소스 (CPU 및 메모리) 를 제한할 수 있습니다. 이는 여러 컨테이너가 돌아가는 환경에서 자원을 공정하게 배분하기 위해 필수적입니다.

메모리와 CPU 제한을 적용하여 컨테이너를 실행해 보겠습니다.

docker run --name limited-nginx -d --memory=512m --cpus=0.5 nginx

이 명령은 다음과 같은 역할을 합니다:

  • --name limited-nginx: 컨테이너 이름을 "limited-nginx"로 지정합니다.
  • -d: 백그라운드에서 실행합니다.
  • --memory=512m: 컨테이너가 사용할 메모리를 최대 512MB 로 제한합니다.
  • --cpus=0.5: 컨테이너가 최대 0.5 개의 CPU 코어만 사용하도록 제한합니다.
  • nginx: Nginx 이미지를 사용합니다.

inspect 명령으로 설정된 제한 값을 확인할 수 있습니다.

docker inspect -f '{{.HostConfig.Memory}}' limited-nginx
docker inspect -f '{{.HostConfig.NanoCpus}}' limited-nginx

첫 번째 명령은 536870912(512MB 를 바이트로 환산한 값) 를 출력하고, 두 번째 명령은 500000000(0.5 CPU 를 나노 단위로 환산한 값) 을 출력합니다.

이러한 제한이 실제 컨테이너에 어떻게 영향을 주는지 실시간으로 확인하려면 stats 명령을 사용합니다.

docker stats limited-nginx

리소스 사용 통계가 실시간으로 스트리밍됩니다. 확인을 마치려면 Ctrl+C를 누르세요.

요약

이번 실습에서는 Docker 의 고급 컨테이너 관리 기술을 살펴보았습니다. 다양한 모드로 컨테이너를 실행하고, 생명주기를 관리하며, 상세 정보를 검사하고, 로그를 다루는 방법을 배웠습니다. 또한 컨테이너 내부에서 명령을 실행하고, 파일을 복사하며, 환경 변수를 설정하고, 리소스 사용량을 제한하는 방법도 익혔습니다. 이러한 기술들은 더 복잡한 시나리오에서 Docker 컨테이너를 다루기 위한 탄탄한 기초가 됩니다.

효과적인 컨테이너 관리는 확장 가능하고 유지보수가 쉬운 컨테이너 기반 애플리케이션을 구축하는 데 필수적입니다. 앞으로 Docker 를 더 깊이 공부하면서, 오늘 배운 기술들이 디버깅, 최적화 및 컨테이너 환경 관리에서 얼마나 가치 있게 쓰이는지 실감하게 될 것입니다.

배운 명령들을 꾸준히 연습하고 Docker 의 다양한 기능을 계속 탐구해 보세요. 컨테이너를 더 많이 다뤄볼수록 실력은 더욱 향상될 것입니다. 즐거운 컨테이너 학습 되세요!