연예이슈

컨테이너와 이미지의 차이, Docker 개념 확실히 잡기

오이슈다 2026. 7. 13. 17:09
반응형

클라우드와 서버 환경을 다루다 보면 Docker라는 이름과 함께 '이미지'와 '컨테이너'라는 두 용어가 끊임없이 등장한다. 두 개념은 서로 밀접하게 연결되어 있으면서도 근본적으로 다른 것을 가리키며, 이 차이를 명확히 이해하지 못하면 Docker의 동작 원리 전체가 모호하게 남는다. 이 글은 가상화라는 배경에서 출발하여 이미지와 컨테이너가 각각 무엇을 의미하는지, 둘의 관계는 어떻게 구성되는지, 그리고 실제 개발과 운영 환경에서 이 구조가 어떤 함의를 가지는지를 체계적으로 정리한다.

 

 

 

▍ 가상화라는 배경에서 컨테이너가 등장한 이유

 

컨테이너와 이미지를 논하기 전에 그 토대가 되는 가상화(Virtualization) 개념을 짚을 필요가 있다. 가상화란 하나의 물리적 컴퓨팅 자원을 논리적으로 분할하거나 통합하여, 실제 자원과 그것을 사용하는 애플리케이션 사이에 추상화 계층을 두는 기술을 말한다. 전통적인 방식에서는 하나의 물리 서버에 하나의 운영체제와 소수의 애플리케이션만을 올려 사용했으나, 이 경우 서버 자원의 상당 부분이 유휴 상태로 낭비되는 문제가 발생했다.

 

이 문제를 해결하기 위해 등장한 것이 서버 가상화이며, 초기에는 하이퍼바이저(Hypervisor) 기반의 가상 머신(VM) 방식이 널리 쓰였다. 가상 머신은 물리 하드웨어 위에 여러 개의 독립된 운영체제를 게스트로 실행하는 구조다. 그러나 각 가상 머신마다 완전한 게스트 운영체제를 포함해야 하므로 용량이 크고, 실행에 걸리는 오버헤드가 상당하다는 한계가 있었다. 컨테이너 기술은 바로 이 오버헤드를 최소화하기 위한 대안으로 발전했으며, Docker는 이 컨테이너 기술을 손쉽게 다룰 수 있도록 표준화한 대표적 플랫폼으로 자리 잡았다.

 

 

 

 

 

 

 

 

▍ Docker 이미지란 무엇인가

 

이미지(Image)는 애플리케이션을 실행하는 데 필요한 모든 것을 담은 정적인 패키지, 즉 읽기 전용 템플릿으로 정의할 수 있다. 여기에는 애플리케이션 코드뿐 아니라 런타임, 시스템 도구, 라이브러리, 환경 설정 등 실행에 요구되는 모든 구성 요소가 포함된다. 중요한 점은 이미지 그 자체가 실행되고 있는 상태가 아니라는 것이다. 이미지는 디스크에 저장된 파일 형태의 설계도이며, 아직 프로세스로 살아 있지 않다.

 

이미지를 흔히 붕어빵 틀이나 요리의 레시피에 비유한다. 틀 자체는 붕어빵이 아니며, 레시피 자체는 완성된 요리가 아니다. 그러나 그 틀과 레시피만 있으면 언제 어디서든 동일한 결과물을 재현할 수 있다. 마찬가지로 하나의 이미지로부터 여러 개의 실행 환경을 반복적으로, 그리고 일관되게 찍어낼 수 있다는 점이 이미지의 본질적 가치다.

 

이미지는 Dockerfile이라는 텍스트 형식의 정의 파일을 통해 빌드된다. Dockerfile에는 어떤 기반 이미지 위에 무엇을 설치하고 어떤 설정을 적용할지가 명령어 단위로 기술되며, 이 파일을 바탕으로 자동화된 방식으로 이미지가 생성된다. 이렇게 만들어진 이미지는 레지스트리(Registry)라는 저장소에 올리고 내려받는 방식으로 여러 환경과 손쉽게 공유할 수 있다.

 

 

 

 

 

 

▍ Docker 컨테이너란 무엇인가

 

컨테이너(Container)는 이미지를 실제로 실행한 인스턴스를 말한다. 정적인 설계도였던 이미지가 메모리에 올라가 프로세스로 살아 움직이는 상태가 바로 컨테이너다. 붕어빵 틀에서 실제로 구워져 나온 붕어빵이 컨테이너에 해당한다고 볼 수 있다. 하나의 틀에서 여러 개의 붕어빵이 나오듯, 하나의 이미지로부터 여러 개의 컨테이너를 동시에 생성할 수 있으며, 각 컨테이너는 서로 격리된 독립적인 실행 공간을 가진다.

 

컨테이너의 핵심 특성은 격리(Isolation)와 경량성(Lightweight)이다. 각 컨테이너는 호스트 운영체제의 커널을 공유하면서도, 네임스페이스와 컨트롤 그룹(cgroups) 같은 리눅스 커널 기능을 통해 프로세스, 네트워크, 파일 시스템 관점에서 서로 분리된다. 즉 하나의 컨테이너 안에서 일어나는 일은 원칙적으로 다른 컨테이너에 영향을 주지 않는다. 별도의 게스트 운영체제를 포함하지 않기 때문에 시작 속도가 매우 빠르고 자원 소모가 적다는 점이 가상 머신과 구별되는 결정적 장점이다.

 

컨테이너는 상태를 가지며 생애주기(Life Cycle)를 따른다. 이미지로부터 생성되고, 시작되어 실행되며, 중지되었다가 다시 시작될 수 있고, 최종적으로 삭제된다. 실행 중 컨테이너 내부에서 변경된 데이터는 기본적으로 그 컨테이너에 한정되며, 컨테이너가 삭제되면 함께 사라진다. 이러한 특성 때문에 보존이 필요한 데이터는 볼륨(Volume)이라는 별도의 저장 방식을 통해 컨테이너 외부에 유지하도록 설계하는 것이 일반적이다.

 

 

 

 

 

 

▍ 이미지와 컨테이너의 결정적 차이

 

지금까지의 설명을 정리하면, 이미지와 컨테이너의 관계는 설계도와 그 설계도로 지어진 건물의 관계와 같다. 이미지는 변하지 않는 읽기 전용 상태로 저장되는 반면, 컨테이너는 그 이미지 위에 쓰기 가능한 계층을 하나 더 얹어 실행되는 동적인 상태다. 두 개념의 차이를 명확히 대비하면 다음 표와 같다.

 

 

 

 

표에서 드러나듯 하나의 이미지는 여러 컨테이너의 공통된 출발점이 된다. 동일한 이미지로 개발 환경, 테스트 환경, 운영 환경에 각각 컨테이너를 띄우면 모든 환경이 완전히 같은 구성으로 동작한다. 이는 특정 환경에서만 애플리케이션이 오작동하는 이른바 '내 컴퓨터에서는 되는데' 문제를 구조적으로 줄여 준다.

 

 

 

▍ Docker의 구조와 동작 원리

 

Docker의 전체 동작은 몇 가지 핵심 명령의 흐름으로 이해할 수 있다. 개발자는 먼저 Dockerfile을 작성하여 이미지를 빌드한다. 완성된 이미지는 로컬에 저장되거나 레지스트리에 업로드된다. 실행 단계에서는 run 명령을 통해 이미지로부터 새로운 컨테이너를 생성하여 곧바로 구동한다. 여기서 자주 혼동되는 부분이 run과 start의 차이인데, run은 이미지로부터 컨테이너를 새로 만들어 실행하는 것이고, start는 이미 존재하지만 중지되어 있는 컨테이너를 다시 켜는 것이다. 이 구분을 놓치면 필요 없는 컨테이너를 중복해서 만들어 내는 실수를 하기 쉽다.

 

컨테이너는 격리되어 있으므로, 호스트와 통신하거나 외부에서 접근하려면 별도의 연결 통로가 필요하다. 대표적으로 포트 매핑(port mapping)은 컨테이너 내부의 특정 포트를 호스트의 포트와 연결하여 외부에서 컨테이너 내부의 서비스에 접근할 수 있게 한다. 볼륨 마운트(volume mount)는 호스트의 디렉터리와 컨테이너 내부의 디렉터리를 연결하여 파일을 실시간으로 공유하는 방식으로, 코드를 수정할 때마다 이미지를 다시 만들 필요 없이 개발을 진행할 수 있게 해 준다.

 

 

 

▍ 이미지를 가볍게 만드는 레이어 구조

 

이미지가 효율적으로 관리될 수 있는 이유는 레이어(Layer) 구조에 있다. Docker 이미지는 하나의 통짜 파일이 아니라 여러 개의 읽기 전용 계층이 쌓여 구성된다. Dockerfile의 각 명령이 하나의 계층을 만들어 내며, 이미 존재하는 계층은 캐시로 재사용된다. 예를 들어 기반 운영체제 계층 위에 라이브러리 계층, 그 위에 애플리케이션 코드 계층이 순서대로 쌓이는 식이다.

 

이 구조의 장점은 저장 공간과 전송 효율에서 두드러진다. 여러 이미지가 동일한 기반 계층을 공유하면 그 계층은 한 번만 저장되며, 이미지를 갱신할 때도 변경된 계층만 새로 빌드하고 전송하면 된다. 컨테이너가 실행될 때는 이 읽기 전용 계층들 위에 얇은 쓰기 가능 계층 하나가 추가되며, 실행 중 발생하는 모든 변경은 이 최상단 계층에만 기록된다. 원본 이미지 계층은 그대로 보존되므로 같은 이미지에서 나온 여러 컨테이너가 서로 독립성을 유지할 수 있다.

 

 

 

 

 

 

▍ 가상 머신과 컨테이너, 무엇이 다른가

 

컨테이너를 제대로 이해하려면 기존의 가상 머신과 비교하는 것이 효과적이다. 가상 머신은 하이퍼바이저 위에서 각기 완전한 게스트 운영체제를 실행하는 반면, 컨테이너는 호스트 운영체제의 커널을 공유하며 애플리케이션 실행에 필요한 부분만을 담는다. 이 근본적 구조 차이가 성능과 이식성 전반에 영향을 준다.

 

 

 

 

다만 이 비교가 곧 우열을 뜻하는 것은 아니다. 가상 머신은 커널까지 완전히 분리되므로 격리 수준이 높아 보안이 특히 중요한 환경에 유리한 측면이 있고, 컨테이너는 경량성과 이식성에서 강점을 가진다. 실제 현장에서는 두 기술을 상황에 맞게 조합하여 사용하는 경우도 많으며, 어느 하나가 다른 하나를 완전히 대체한다고 단정하기는 어렵다. 이는 기술 선택이 언제나 요구사항과 제약 조건에 따라 달라지는 문제임을 보여 준다.

 

 

 

▍ 실무 관점에서의 함의와 고려사항

 

이미지와 컨테이너의 분리는 현대적인 개발 및 배포 방식과 자연스럽게 맞물린다. 애플리케이션이 여러 독립적인 구성 요소로 나뉘는 마이크로서비스 아키텍처에서는, 각 서비스를 개별 컨테이너로 묶어 관리하는 방식이 특히 적합하다. 또한 코드 변경이 발생할 때마다 자동으로 이미지를 빌드하고 배포하는 지속적 통합 및 배포 흐름과도 잘 결합된다. 한 번 검증된 이미지를 그대로 여러 환경에 배포하기 때문에, 환경 간 차이로 인한 오류의 여지가 크게 줄어든다.

 

다만 컨테이너를 다룰 때 몇 가지 세심한 고려가 필요하다. 첫째, 컨테이너 내부의 변경 데이터는 휘발성이 강하므로, 보존이 필요한 데이터는 반드시 볼륨 등 외부 저장 수단으로 분리해야 한다. 둘째, 실습이나 개발을 반복하다 보면 중지된 컨테이너와 사용하지 않는 이미지가 계속 쌓여 저장 공간을 잠식하므로, 주기적인 정리가 요구된다. 이때 사용하지 않는 자원을 일괄 삭제하는 명령은 실행 전에 대상을 반드시 확인해야 하며, 그렇지 않으면 필요한 이미지까지 지워질 수 있다. 셋째, 컨테이너의 격리 수준은 가상 머신보다 낮으므로, 다중 사용자 환경에서 컨테이너 간 격리를 강화하는 문제는 여전히 중요한 설계 과제로 남는다.

 

 

 

▍ 정리

 

이미지와 컨테이너는 Docker를 이해하는 데 있어 반드시 구분해야 하는 두 축이다. 이미지는 실행에 필요한 모든 것을 담은 변하지 않는 설계도이며, 컨테이너는 그 설계도로부터 만들어져 실제로 살아 움직이는 실행 인스턴스다. 하나의 이미지에서 여러 컨테이너가 일관되게 생성될 수 있다는 점, 이미지가 레이어 구조로 효율적으로 관리된다는 점, 그리고 컨테이너가 커널을 공유하여 가볍고 빠르게 동작한다는 점이 이 기술의 핵심을 이룬다. 이 관계를 명확히 잡아 두면, Docker를 활용한 개발과 배포의 전체 그림이 한결 선명하게 정리될 것이다. 개념을 충분히 이해했다면, 다음 단계로는 간단한 Dockerfile을 직접 작성하고 이미지를 빌드해 컨테이너로 띄워 보며 그 동작을 눈으로 확인해 보기를 권한다.

 

 

반응형