Docker 컨테이너 run 명령어를 사용하여 컨테이너 관리하는 방법

DockerBeginner
지금 연습하기

소개

이 랩에서는 docker container run 명령을 사용하여 컨테이너를 효과적으로 관리하는 실질적인 경험을 얻게 됩니다. 백그라운드 실행을 위해 컨테이너를 분리 모드 (detached mode) 로 실행하고, 더 쉽게 식별할 수 있도록 사용자 정의 이름을 할당하는 방법을 배우게 됩니다.

또한, STDIN 을 열어둔 상태로 실행 중인 컨테이너에 연결하고, 외부 접근을 위해 컨테이너 포트를 호스트에 게시하며, 데이터 지속성을 보장하기 위해 볼륨을 마운트하고, 환경 변수를 설정하고 호스트 항목을 추가하여 컨테이너를 구성하는 방법을 탐구할 것입니다. 이러한 기본적인 기술은 Docker 화된 애플리케이션을 구축하고 관리하는 데 필수적입니다.

분리 모드로 컨테이너 실행 및 이름 할당

이 단계에서는 Docker 컨테이너를 분리 모드 (detached mode) 로 실행하고 사용자 정의 이름을 할당하는 방법을 배우게 됩니다. 분리 모드로 컨테이너를 실행한다는 것은 컨테이너가 백그라운드에서 실행되며, 터미널에서 직접 출력을 볼 수 없다는 것을 의미합니다. 이름을 할당하면 나중에 컨테이너를 더 쉽게 식별하고 관리할 수 있습니다.

먼저, hello-world 이미지를 가져와 보겠습니다. 이것은 Docker 가 제대로 작동하는지 테스트하는 데 유용한 매우 작은 이미지입니다.

docker pull hello-world

이미지가 가져와지고 성공적으로 가져왔음을 확인하는 메시지가 표시되어야 합니다.

이제 hello-world 컨테이너를 분리 모드로 실행해 보겠습니다. 분리 모드에는 -d 플래그를 사용하고, 이름을 할당하기 위해 --name 플래그를 사용합니다. 이 컨테이너의 이름을 my-hello-world로 지정해 보겠습니다.

docker run -d --name my-hello-world hello-world

이 명령을 실행하면 Docker 는 컨테이너 ID 인 긴 문자열을 출력합니다. 이는 컨테이너가 백그라운드에서 시작되었음을 나타냅니다.

컨테이너가 실행 중인지 확인하려면 docker ps 명령을 사용할 수 있습니다. 이 명령은 현재 실행 중인 모든 컨테이너를 나열합니다.

docker ps

실행 중인 컨테이너 목록이 표시되어야 하며, 그 중 하나는 my-hello-world라는 이름을 가져야 합니다. STATUS 열에는 컨테이너가 몇 초 전에 종료되었음을 표시해야 합니다. hello-world 컨테이너는 잠시 실행되어 메시지를 출력한 다음 종료되도록 설계되었습니다. 종료되었더라도 분리 모드로 실행되었기 때문에 docker ps에 계속 나열됩니다.

종료된 컨테이너를 포함한 모든 컨테이너를 보려면 docker ps -a 명령을 사용할 수 있습니다.

docker ps -a

이렇게 하면 my-hello-world가 상태 (Exited) 와 함께 목록에 표시됩니다.

실행 중인 컨테이너에 연결하고 STDIN 유지

이 단계에서는 실행 중인 컨테이너에 연결하고 표준 입력 (STDIN) 을 열어두는 방법을 배우게 됩니다. 이는 셸과 같이 입력을 예상하는 프로세스를 실행하는 컨테이너와 상호 작용하는 데 유용합니다.

이전 단계에서는 즉시 종료되는 hello-world 컨테이너를 실행했습니다. 연결을 시연하기 위해, 계속 실행되는 컨테이너가 필요합니다. 이를 수행하는 간단한 방법은 컨테이너에서 대화형 셸을 실행하는 것입니다.

많은 애플리케이션의 일반적인 기본 이미지인 ubuntu 이미지를 가져와 보겠습니다.

docker pull ubuntu

이제 분리 모드 (-d) 로 ubuntu 컨테이너를 실행하고, 가상 TTY(-t) 를 할당하고, STDIN 을 열어둡니다 (-i). 또한 my-ubuntu라는 이름을 할당합니다. 컨테이너 내에서 실행할 명령은 Bash 셸의 경로인 /bin/bash입니다.

docker run -itd --name my-ubuntu ubuntu /bin/bash

-i 플래그는 STDIN 을 열어두어 컨테이너에 입력을 보낼 수 있도록 합니다. -t 플래그는 대화형 셸 세션에 필요한 가상 TTY 를 할당합니다. -d 플래그는 분리 모드로 컨테이너를 실행합니다.

컨테이너 ID 가 터미널에 출력되어 컨테이너가 백그라운드에서 실행 중임을 나타냅니다.

이제 docker attach 명령을 사용하여 실행 중인 my-ubuntu 컨테이너에 연결해 보겠습니다.

docker attach my-ubuntu

이 명령을 실행하면 ubuntu 컨테이너 내부의 Bash 셸 프롬프트가 표시됩니다. 이제 컨테이너의 표준 입력, 출력 및 오류 스트림에 연결되었습니다.

이제 컨테이너의 셸과 상호 작용할 수 있습니다. 예를 들어, ls 명령을 실행하여 컨테이너 내부의 현재 디렉터리에 있는 파일을 나열할 수 있습니다.

ls

Ubuntu 컨테이너의 루트 디렉터리 (/) 의 내용이 표시되어야 합니다.

컨테이너를 중지하지 않고 분리하려면 특정 키 시퀀스를 사용해야 합니다: CTRL+p를 누른 다음 CTRL+q를 누릅니다. 지금 CTRL+p를 누른 다음 CTRL+q를 눌러보세요.

호스트 머신의 터미널 프롬프트로 돌아와야 합니다. 컨테이너는 여전히 백그라운드에서 실행 중입니다. docker ps를 사용하여 이를 확인할 수 있습니다.

docker ps

my-ubuntu가 실행 중인 컨테이너로 나열되어야 합니다.

단순히 연결된 상태에서 CTRL+c를 누르면 컨테이너 내부에서 실행 중인 프로세스 (Bash 셸) 에 신호가 전송되어 컨테이너가 중지될 가능성이 높습니다. CTRL+p를 누른 다음 CTRL+q를 누르는 것이 컨테이너를 중지하지 않고 분리하는 표준 방법입니다.

컨테이너 포트를 호스트에 공개

이 단계에서는 Docker 컨테이너의 포트를 호스트 머신에 게시하는 방법을 배우게 됩니다. 이렇게 하면 호스트의 네트워크에서 컨테이너 내에서 실행되는 서비스에 액세스할 수 있습니다.

먼저, 이전 단계에서 my-ubuntu 컨테이너를 중지하고 제거하여 충돌을 방지합니다.

docker stop my-ubuntu
docker rm my-ubuntu

각 명령 후에 컨테이너의 이름이 출력되어 중지되고 제거되었음을 확인해야 합니다.

이제 컨테이너 내에서 간단한 웹 서버를 실행하고 해당 포트를 호스트에 게시합니다. 인기 있는 웹 서버인 nginx 이미지를 사용합니다.

nginx 이미지를 가져와 보겠습니다.

docker pull nginx

이제 분리 모드 (-d) 로 nginx 컨테이너를 실행하고 컨테이너 내부의 포트 80 을 호스트 머신의 포트 8080 에 게시합니다. 포트 게시를 위해 -p 플래그를 host_port:container_port 형식으로 사용합니다. 또한 my-nginx라는 이름을 할당합니다.

docker run -d --name my-nginx -p 8080:80 nginx

-p 8080:80 부분은 컨테이너 내부의 포트 80(Nginx 가 기본적으로 수신 대기하는 곳) 을 호스트 머신의 포트 8080 에 매핑합니다.

컨테이너 ID 가 출력되어 컨테이너가 백그라운드에서 실행 중임을 나타냅니다.

포트가 올바르게 게시되었고 웹 서버에 액세스할 수 있는지 확인하려면 호스트 머신에서 curl 명령을 사용하여 포트 8080 의 localhost에 액세스할 수 있습니다.

curl http://localhost:8080

터미널 출력에 기본 Nginx 환영 HTML 페이지가 표시되어야 합니다. 이는 호스트의 포트 8080 을 통해 컨테이너 내에서 실행되는 Nginx 웹 서버에 액세스할 수 있음을 확인합니다.

docker ps를 사용하여 실행 중인 컨테이너와 게시된 포트를 볼 수도 있습니다.

docker ps

출력에서 my-nginx가 나열되고 PORTS 열 아래에 0.0.0.0:8080->80/tcp가 표시되어 컨테이너 내부의 포트 80 이 모든 호스트 인터페이스의 포트 8080 에 매핑되었음을 나타냅니다.

데이터 지속성을 위해 볼륨 마운트

이 단계에서는 Docker 컨테이너에서 생성되고 사용되는 데이터를 유지하기 위해 Docker 볼륨을 사용하는 방법을 배우게 됩니다. 기본적으로 컨테이너 내부의 데이터는 일시적입니다. 컨테이너가 제거되면 손실됩니다. 볼륨은 컨테이너 파일 시스템 외부에 데이터를 저장하는 방법을 제공하여 컨테이너가 중지되거나 제거된 후에도 데이터를 유지할 수 있도록 합니다.

먼저, 이전 단계에서 my-nginx 컨테이너를 중지하고 제거합니다.

docker stop my-nginx
docker rm my-nginx

이제 Docker 볼륨을 생성합니다. 볼륨은 Docker 에서 관리하며 호스트 머신의 전용 영역에 저장됩니다.

docker volume create my-volume

볼륨 이름 (my-volume) 이 출력되어 생성되었음을 확인해야 합니다.

docker volume ls 명령을 사용하여 기존 볼륨을 나열할 수 있습니다.

docker volume ls

볼륨 목록에 my-volume이 표시되어야 합니다.

이제 새로운 nginx 컨테이너를 실행하고 my-volume을 컨테이너 내부의 기본 Nginx 웹루트 디렉터리인 /usr/share/nginx/html에 마운트합니다. 즉, 컨테이너 내부의 /usr/share/nginx/html에 배치된 모든 파일은 실제로 호스트의 my-volume에 저장됩니다.

컨테이너를 분리 모드 (-d) 로 실행하고, 컨테이너 내부의 포트 80 을 호스트의 포트 8081 에 게시 (-p 8081:80) 하고, 이름을 할당 (my-nginx-volume) 하고, -v 플래그를 사용하여 볼륨을 마운트합니다. 명명된 볼륨을 마운트하는 형식은 volume_name:container_path입니다.

docker run -d --name my-nginx-volume -p 8081:80 -v my-volume:/usr/share/nginx/html nginx

컨테이너 ID 가 출력되어 컨테이너가 실행 중임을 나타냅니다.

이제 마운트된 볼륨에 간단한 HTML 파일을 배치해 보겠습니다. docker exec를 사용하여 실행 중인 컨테이너 내부에서 명령을 실행하여 이 작업을 수행할 수 있습니다. 간단한 내용으로 /usr/share/nginx/htmlindex.html이라는 파일을 생성합니다.

docker exec my-nginx-volume sh -c 'echo "<h1>Hello from the volume!</h1>" > /usr/share/nginx/html/index.html'

이 명령은 my-nginx-volume 컨테이너 내부에서 셸 (sh -c) 을 실행하고 echo 명령을 실행하여 index.html 파일을 생성합니다.

이제 호스트의 포트 8081 에서 웹 서버에 액세스하여 방금 생성한 index.html 파일의 내용을 확인해 보겠습니다.

curl http://localhost:8081

출력에 <h1>Hello from the volume!</h1>이 표시되어야 합니다. 이는 컨테이너 내부에서 생성한 파일이 Nginx 에서 제공되고 있으며, 마운트된 볼륨에 기록되었으므로 데이터가 유지됨을 확인합니다.

유지성을 시연하기 위해 my-nginx-volume 컨테이너를 중지하고 제거해 보겠습니다.

docker stop my-nginx-volume
docker rm my-nginx-volume

이제 새로운 컨테이너를 실행하여 동일한 볼륨을 마운트해 보겠습니다. 이 새 컨테이너의 이름을 my-nginx-volume-new로 지정하고 포트 80 을 호스트 포트 8082 에 게시합니다.

docker run -d --name my-nginx-volume-new -p 8082:80 -v my-volume:/usr/share/nginx/html nginx

새 컨테이너가 실행 중이며 동일한 my-volume을 사용하고 있습니다. 포트 8082 에서 웹 서버에 액세스해 보겠습니다.

curl http://localhost:8082

출력에 여전히 <h1>Hello from the volume!</h1>이 표시되어야 합니다. 이는 index.html 파일이 my-volume에 저장되었고, 원래 컨테이너가 제거된 후에도 유지되었기 때문입니다. 새 컨테이너는 동일한 볼륨을 마운트하여 이전에 기록된 데이터에 액세스할 수 있습니다.

이는 컨테이너 수명 주기와 독립적으로 데이터를 유지하기 위한 볼륨의 강력함을 보여줍니다.

환경 변수 설정 및 호스트 항목 추가

이 단계에서는 Docker 컨테이너에 대한 환경 변수를 설정하는 방법과 컨테이너의 /etc/hosts 파일에 사용자 지정 항목을 추가하는 방법을 배우게 됩니다. 환경 변수는 컨테이너 내에서 실행되는 애플리케이션을 구성하는 일반적인 방법이며, 호스트 항목을 추가하는 것은 서비스 검색 또는 컨테이너 내에서 DNS 확인을 재정의하는 데 유용할 수 있습니다.

먼저, 이전 단계에서 my-nginx-volume-new 컨테이너를 중지하고 제거합니다.

docker stop my-nginx-volume-new
docker rm my-nginx-volume-new

이제 간단한 컨테이너를 실행하고 환경 변수를 설정합니다. 다시 ubuntu 이미지를 사용하고 환경 변수의 값을 출력하는 명령을 실행합니다. MY_VARIABLE이라는 환경 변수를 값 hello_docker로 설정합니다. -e 플래그를 사용하여 환경 변수를 VARIABLE_NAME=value 형식으로 설정합니다.

docker run --rm -e MY_VARIABLE=hello_docker ubuntu env | grep MY_VARIABLE

이 명령에서:

  • --rm은 종료 시 컨테이너를 자동으로 제거합니다.
  • -e MY_VARIABLE=hello_docker는 컨테이너 내부에서 환경 변수 MY_VARIABLEhello_docker로 설정합니다.
  • ubuntu는 우리가 사용하는 이미지입니다.
  • env는 모든 환경 변수를 출력하기 위해 컨테이너 내부에서 실행되는 명령입니다.
  • | grep MY_VARIABLEMY_VARIABLE을 포함하는 줄만 표시하도록 출력을 필터링합니다.

터미널 출력에 MY_VARIABLE=hello_docker가 표시되어야 합니다. 이는 환경 변수가 컨테이너 내부에서 성공적으로 설정되었음을 확인합니다.

다음으로, 컨테이너의 /etc/hosts 파일에 사용자 지정 호스트 항목을 추가하는 방법을 배우겠습니다. 이는 외부 DNS 에 의존하지 않고 특정 호스트 이름을 특정 IP 주소로 확인해야 하는 경우에 유용할 수 있습니다. 이를 위해 --add-host 플래그를 hostname:ip_address 형식으로 사용합니다.

다른 ubuntu 컨테이너를 실행하고 호스트 이름 my-service를 IP 주소 192.168.1.100에 매핑하는 호스트 항목을 추가합니다. 그런 다음 cat 명령을 사용하여 컨테이너 내부의 /etc/hosts 파일의 내용을 표시하고 grep을 사용하여 추가된 항목을 확인합니다.

docker run --rm --add-host my-service:192.168.1.100 ubuntu cat /etc/hosts | grep my-service

이 명령에서:

  • --rm은 종료 후 컨테이너를 제거합니다.
  • --add-host my-service:192.168.1.100은 컨테이너의 /etc/hosts 파일에 my-service192.168.1.100에 매핑하는 항목을 추가합니다.
  • ubuntu는 이미지입니다.
  • cat /etc/hosts는 호스트 파일을 출력하기 위해 컨테이너 내부에서 실행되는 명령입니다.
  • | grep my-servicemy-service가 있는 줄을 찾기 위해 출력을 필터링합니다.

터미널에 192.168.1.100 my-service와 유사한 출력이 표시되어야 합니다. 이는 사용자 지정 호스트 항목이 컨테이너의 /etc/hosts 파일에 추가되었음을 확인합니다.

필요한 경우 환경 변수 설정과 호스트 항목 추가를 단일 docker run 명령으로 결합할 수 있습니다.

요약

이 랩에서는 docker run 명령을 사용하여 컨테이너를 관리하는 방법을 배웠습니다. -d 플래그를 사용하여 분리 모드 (detached mode) 로 컨테이너를 실행하고 --name 플래그로 사용자 지정 이름을 할당하는 것으로 시작하여 docker psdocker ps -a로 상태를 확인했습니다.

그런 다음 STDIN 을 열어둔 상태로 실행 중인 컨테이너에 연결하는 방법, 네트워크 접근성을 위해 -p 플래그를 사용하여 컨테이너 포트를 호스트에 게시하는 방법, 컨테이너의 수명 주기 (lifecycle) 를 넘어 데이터 지속성을 보장하기 위해 -v 플래그로 볼륨을 마운트하는 방법, 그리고 -e 플래그로 환경 변수를 설정하고 --add-host 플래그를 사용하여 호스트 항목을 추가하여 컨테이너의 환경을 구성하는 방법을 살펴보았습니다.