이번 포스팅에서는 도커(Docker)의 컨테이너(Container) 기술에 대해 알아보고자 한다.
< 목차 >
- 컨테이너란?
- 컨테이너 가상화 vs VM 가상화
- 기본적인 컨테이너 명령어
1. 컨테이너란?
컨테이너는 애플리케이션을 언제든 실행 가능하도록 필요한 모든 요소를(소스코드, 구성요소, 종속성 등) 하나의 런타임 환경으로 패키징 한 논리적 공간을 말한다. 어려운 말들로 포장되어 있을 뿐, 도커 컨테이너는 말 그대로 물건을 담는 컨테이너와 다를 것이 없다. 예를 들어 애플리케이션이 들어 있는 어떤 상자를 상상해보자. 이 상자 안에는 애플리케이션과 애플리케이션을 실행할 컴퓨터(IP 주소, 컴퓨터 이름, 디스크 드라이브)가 함께 들어있다.
호스트명, IP 주소, 파일 시스템까지 이들은 모두 도커가 만들어낸 가상 리소스이다. 이들이 서로 엮여 애플리케이션이 동작할 수 있는 환경이 만들어지는 것이다. 그리고 이러한 환경이 바로 앞서 얘기한 상자, 곧 "컨테이너"이다. 이 상자는 어떤 컴퓨터 상에서 동작하는 것이고, 이 컴퓨터는 이 상자 말고도 다른 상자를 여러 개 실행할 수 있다. 또한 이들 상자는 서로 독립적인 환경을 갖지만 상자가 실행되는 컴퓨터의 CPU와 메모리, 운영체제를 공유한다.
2. 컨테이너 가상화 vs VM 가상화
가상화(Virtualization)는 컴퓨터의 물리적 자원을 추상화하여, 이를 다수의 사용자나 애플리케이션에서 공유하고 동시에 사용할 수 있도록 하는 기술을 말한다. 가상화를 통해 하나의 물리적 하드웨어 위에 여러 개의 가상 환경을 생성하고 운영할 수 있으며, 일반적으로 서버, 스토리지, 네트워크, 애플리케이션 등을 가상화하여 하드웨어 리소스를 효율적으로 사용하는데 그 목적이 있다.
가상화 기술에는 크게 (1)가상화를 관리하는 소프트웨어(주로 Hypervisor)를 사용하여 하나의 물리적 머신에서 가상 머신(VM)을 만드는 VM 가상화 와 (2)도커(Docker)와 같은 컨테이너 가상화 가 있다. 두 가지 가상화 모두 실행하고자 하는 애플리케이션 프로세스 및 종속 요소와 소스 등을 패키징하여 HostOS와 격리된 환경을 제공한다. 다만, VM 가상화는 실제 호스트 운영체제와 같이 별도의 GuestOS를 두고 원하는 애플리케이션을 설치하는 하드웨어 수준의 가상화를 구현하는 반면, 컨테이너 가상화는 VM 가상화에 비해 경량이면서 호스트 운영체제의 커널(Kernel)을 공유하는 운영체제 수준의 가상화를 구현한다.
컨테이너 가상화
- 호스트 컴퓨터는 별도의 호스트명, IP 주소와 디스크를 갖는다.
- 모든 컨테이너는 호스트 컴퓨터의 운영체제, CPU, 메모리를 공유한다.
- 각 컨테이너는 독립적인 호스트명, IP 주소, 디스크를 갖는다.
VM 가상화
- 호스트 컴퓨터는 별도의 호스트명, IP 주소와 디스크를 갖는다.
- 가상 머신은 호스트 컴퓨터의 CPU와 메모리를 공유하지만, 각 가상 머신에는 고정된 크기의 리소스가 할당된다.
- 각 가상 머신은 독립적인 운영체제, 호스트명, IP 주소, 디스크를 갖는다.
가상 머신은 애플리케이션이 실행될 독립적 환경이 생긴다는 점에서는 컨테이너와 큰 차이가 없다. 다만 가상 머신은 컨테이너와 달리 호스트 컴퓨터의 운영체제를 공유하지 않고 별도의 운영체제를 필요로 한다. 각각의 가상 머신이 자신만의 운영체제를 별도로 갖는다는 차이가 의미하는 바는 상당히 크다. 이 운영체제는 애플리케이션이 사용해야 할 CPU와 메모리 자원을 상당량 차지한다. 또한 운영체제의 라이센스 비용과 운영체제 업데이트 설치 부담 역시 추가로 생기게 된다. 하지만, 컨테이너는 이러한 단점을 해결할 수 있다. 각각의 컨테이너는 호스트 컴퓨터의 운영체제를 공유하므로 필요한 리소스가 크게 경감된다. 그만큼 실행도 빠르고 같은 호스트 컴퓨터에서 가상 머신에 비해 더 많은 수의 애플리케이션을 실행할 수 있다.
3. 기본적인 컨테이너 명령어
$ docker container run [이미지명]
- docker container run 명령은 컨테이너로 애플리케이션을 실행하라는 도커 명령이다.
- 이미지를 이용해 컨테이너를 실행하려면 먼저 이미지가 있어야 한다.
- 로컬에 해당하는 이미지가 없으면 이미지를 내려받고, 내려받은 이미지를 사용해 컨테이너를 실행한다.
- 이미지에는 애플리케이션을 실행하는데 필요한 모든 내용과 함께 애플리케이션을 실행하는 방법이 정의되어 있다.
$ docker container run --interactive --tty [이미지명]
- 컨테이너를 실행하고 실행된 컨테이너에 마치 원격 컴퓨터에 접속하듯 터미널을 통해 접근할 수 있게 하는 명령어이다.
- 터미널 세션으로 조작할 수 있는 대화식 컨테이너를 실행하도록 한다.
- --interactive , -i
- 해당 플래그를 사용하면 컨테이너에 접속된 상태가 된다.
- 이 옵션은 컨테이너의 표준 입력(STDIN)을 열어둔다.
- --tty , -t
- 해당 플래그는 터미널 세션을 통해 컨테이너를 조작하겠다는 의미이다.
- 가상 터미널(TTY; Teletypewriter)을 할당.
- --interactive , -i
$ docker exec --interactive --tty [컨테이너명/ID] /bin/sh
- exec 명령어는 실행 중인 도커 컨테이너 내부에서 새로운 명령을 실행할 때 사용한다.
- docker exec는 컨테이너가 실행 중일 때만 사용할 수 있으며, 컨테이너 내부에서 프로세스를 시작하기 위해 주로 사용한다.
$ docker container ls
- 현재 실행 중인 모든 컨테이너에 대한 정보를 볼 수 있다.
- 컨테이너마다 컨테이너의 바탕이 된 이미지, 컨테이너 ID, 컨테이너 실행 후 도커가 실행한 명령어 등이 출력된다.
- 도커는 컨테이너를 실행할 때마다 무작위로 생성한 ID 값을 부여한다. 그리고 이 ID 값 중 일부분이 호스트명이 된다.
$ docker ps
- docker container ls 명령과 마찬가지로 실행 중인 컨테이너의 목록을 보여준다. (초기 Docker 버전에서 사용되던 명령어)
- ps : process status
$ docker container ls --all --quiet
- --all , -a
- 해당 플래그를 추가하면 실행 중이지 않은 컨테이너를 포함하여 모든 컨테이너를 표시한다.
- --quiet , -q
- 컨테이너 ID만을 출력하도록 한다.
- 다른 도커 명령어와 함께 사용하기 편하다.
$ docker container rm --force $(docker container ls --all --quiet)
- 호스트 컴퓨터에 존재하는 모든 컨테이너의 목록을 만든 다음 이들 컨테이너를 제거하는 명령어이다.
- --force , -f
- --force 플래그를 사용하면 실행 중인 컨테이너라도 바로 삭제가 가능하다.
- $( )
- $( ) 문법은 괄호 안 명령의 출력을 다른 명령으로 전달하는 역할을 한다.
$ docker container top [컨테이너ID]
- docker container top 명령은 대상 컨테이너에서 실행 중인 프로세스의 목록을 보여준다.
- 컨테이너에서 실행 중인 프로세스가 두개 이상이라면, 모든 프로세스에 대한 정보가 출력된다.
$ docker container logs [컨테이너ID]
- docker container logs 명령은 대상 컨테이너에서 수집된 모든 로그를 출력한다.
$ docker container inspect [컨테이너ID]
- docker container inspect 명령은 대상 컨테이너의 상세한 정보를 보여준다.
$ docker container stats [컨테이너ID]
- docker container stats 명령으로도 실행 중인 컨테이너의 상태를 확인할 수 있다.
- 실시간으로 컨테이너의 CPU, 메모리, 네트워크, 디스크 사용량을 볼 수 있다.
컨테이너를 사용해 웹 사이트 호스팅하기
도커를 사용하는 주목적은 웹 사이트, 배치 프로세스, 데이터베이스 같은 서버 애플리케이션을 실행하는 것이다. Nginx 이미지를 사용해 컨테이너에서 간단한 웹 사이트를 호스팅해보도록 하자.
$ docker container run --detach --publish 8080:80 nginx:1.23.1-alpine
- 컨테이너가 백그라운드에서 동작하면서 네트워크를 주시하게 하려면 docker container run 명령에 --detach , --publish 두 개의 플래그를 적용해야 한다.
- --detach , -d
- 컨테이너를 백그라운드에서 실행하며 컨테이너 ID를 출력한다.
- --detach 플래그를 적용해 실행한 컨테이너는 마치 리눅스 데몬이나 윈도우 서비스처럼 백그라운드로 동작하며 겉으로 드러나지 않는다.
- --publish , -p
- 컨테이너의 포트를 호스트 컴퓨터에 공개한다.
- --publish [호스트 포트]:[컨테이너 포트]
컨테이너의 포트를 호스트 컴퓨터에 공개하는 원리는 조금 복잡하다. 도커를 설치하면 호스트 컴퓨터의 네트워크 계층에 도커가 끼어들게 되는데, 그러면 호스트 컴퓨터에서 들어오고 나가는 네트워크 트래픽을 모두 도커가 가로채서 그 중 필요한 것을 컨테이너에 전달할 수 있다.
컨테이너는 기본적으로 외부 환경에 노출되지 않는다. 각 컨테이너는 고유의 IP 주소를 갖지만, 이 IP 주소는 도커가 관리하는 내부 가상 네트워크의 주소지 호스트 컴퓨터가 연결된 물리 네트워크에 연결된 것이 아니다. 컨테이너의 포트를 공개한다는 것은 도커가 호스트 컴퓨터의 포트를 주시하다가 해당 포트로 들어오는 트래픽을 컨테이너로 전달해 주는 것이라고 할 수 있다.
References
- https://www.docker.com/resources/what-container/
- https://www.manning.com/books/learn-docker-in-a-month-of-lunches
'Infra > Docker' 카테고리의 다른 글
Docker - 이미지(Image) (0) | 2024.03.03 |
---|