Docker 입문 (컨테이너, 격리, 이미지)
클라우드 네이티브라는 단어를 들을 때 가장 먼저 떠오르는 도구가 Docker다. 거의 모든 현대 백엔드 시스템이 Docker를 통해 패키징되고 배포되며, 쿠버네티스·MSA 같은 후속 개념도 모두 컨테이너 위에서 동작한다. 그럼에도 처음 Docker를 마주한 학습자에게는 컨테이너·이미지·격리 같은 단어가 동시에 쏟아져 들어와 머릿속이 엉키기 십상이다. 이 글은 Docker가 무엇이고, 왜 등장했으며, 컨테이너가 어떻게 서로를 격리하는지를 정보처리기사 시험 출제 범위와 실무 입문에 모두 닿도록 정리한다(출처: Docker 공식 문서). 제가 처음 Docker를 만져본 건 학교 클라우드 네이티브 수업 첫 주였는데, 솔직히 가상머신을 이미 알고 있다 보니 "이미 가상머신이 있는데 왜 또?"라는 의문이 들었고, 그 의문이 풀린 순간이 입문의 진짜 시작이었다.

Docker란 무엇인가, 컨테이너의 등장
Docker는 애플리케이션과 그 실행에 필요한 모든 환경(라이브러리·설정·바이너리)을 하나의 패키지로 묶어 어디서든 동일하게 실행할 수 있게 만드는 컨테이너 플랫폼이다. 여기서 컨테이너(Container)란 호스트 운영체제의 커널을 공유하면서도 프로세스·네트워크·파일시스템이 격리된 가벼운 실행 환경을 가리킨다. 비교 대상으로 흔히 거론되는 가상머신(VM)이 게스트 OS 전체를 통째로 띄우는 무거운 격리라면, 컨테이너는 OS 커널을 공유하면서 사용자 공간만 따로 잡는 가벼운 격리라고 이해하면 된다.
Docker가 등장한 2013년 이전에는 "내 노트북에서는 되는데 서버에서는 안 된다"는 환경 차이 문제가 만성적인 골칫거리였다. 운영체제 버전, 라이브러리 충돌, 환경 변수 누락 같은 사소한 차이가 배포 때마다 사고를 일으켰고, 이를 해결하기 위한 기존의 방법은 가상머신 이미지를 통째로 배포하는 무거운 방식이었다. 컨테이너는 이 문제를 "이미지"라는 가벼운 단위로 풀어낸다. 한 번 빌드한 이미지는 어떤 호스트에서든 같은 결과를 낸다는 약속, 즉 재현 가능성(reproducibility)을 표준화한 것이 Docker의 본질적 기여다.
추가로 Docker는 패키징·배포·실행을 하나의 일관된 명령어 체계로 통합했다. 개발자는 Dockerfile이라는 텍스트 한 장으로 환경을 코드화하고, docker build로 이미지를 만들고, docker run으로 띄우면 된다. 제 경험상 이 단순한 흐름이 가져다준 가장 큰 효과는 "팀 신규 입사자의 환경 셋업 시간"이 며칠에서 한 시간으로 줄었다는 점이었다. 솔직히 이건 예상 밖이었는데, Docker의 가치는 화려한 신기술보다 "셋업 가이드 문서"라는 골치 아픈 산출물을 거의 없애 준다는 운영 효과에서 가장 강하게 느껴졌다.
컨테이너 격리의 핵심, 네임스페이스와 cgroups
컨테이너가 서로를 어떻게 격리하는지를 이해하려면 리눅스 커널의 두 가지 기능을 알아야 한다. 네임스페이스(Namespace)와 cgroups다. 둘 다 Docker가 발명한 것이 아니라 리눅스 커널에 내장된 기능이며, Docker는 이 두 기능을 사용자 친화적인 방식으로 묶어 제공할 뿐이다(출처: Linux man-pages namespaces).
네임스페이스란 한 컨테이너가 자신만의 프로세스 ID·네트워크·마운트·사용자 ID 공간을 가지도록 만드는 격리 메커니즘이다. 같은 호스트 위에서 컨테이너 A와 B가 동작하더라도, A 안에서 보는 프로세스 목록·네트워크 인터페이스·파일시스템은 B와 완전히 분리되어 있다. 여기서 PID 네임스페이스란 같은 1번 프로세스(init)를 컨테이너마다 따로 가질 수 있게 만드는 분리 공간이며, 마운트 네임스페이스는 컨테이너마다 자신만의 / 루트 디렉터리를 갖게 만든다.
cgroups(Control Groups)는 자원 사용량을 제한하는 메커니즘이다. CPU·메모리·디스크 I/O·네트워크 대역폭을 컨테이너 단위로 상한값을 두어 분배한다. 한 컨테이너가 폭주해도 다른 컨테이너의 자원을 모두 빨아먹는 사태를 막아 주는 역할이다. 제가 직접 1GB 메모리 제한을 걸고 메모리 누수 코드를 컨테이너 안에서 실행해 본 경험이 있는데, 누수가 1GB에 도달하자 컨테이너 내부 프로세스만 OOM Killer로 종료되고 호스트 전체는 멀쩡한 모습을 직접 확인하면서 cgroups의 가치가 가장 직관적으로 와닿았다. 여기서 OOM Killer란 메모리 부족 시 가장 많이 쓰는 프로세스를 강제로 종료하는 리눅스 커널 기능을 가리킨다.
이 두 기능이 결합되면 결과적으로 한 호스트 위에 수십·수백 개의 가벼운 격리 환경을 동시에 띄울 수 있게 된다. 가상머신 한 대가 1~2GB 메모리를 기본으로 점유한다면, 컨테이너 한 개는 수십 MB로 충분하다. 같은 하드웨어로 더 많은 워크로드를 돌릴 수 있다는 의미이며, 이는 곧 클라우드 비용 절감과 직결된다.
이미지와 컨테이너의 관계, 첫 실행 예제
Docker를 다루며 가장 자주 헷갈리는 짝이 이미지(Image)와 컨테이너(Container)의 차이다. 비유하자면 이미지는 "설계도"이고 컨테이너는 "그 설계도로 만든 실제 기계"다. 한 이미지에서 여러 컨테이너를 동시에 실행할 수 있고, 컨테이너는 종료된 뒤에도 다시 같은 이미지에서 새로 띄울 수 있다. 이미지는 변경 불가능(immutable)하며, 변경은 새 이미지를 만들어 태그를 올리는 방식으로 이루어진다.
이미지를 표현하는 텍스트 파일이 Dockerfile이다. 다음과 같은 다섯 줄짜리 Dockerfile은 파이썬 3.12 위에서 Flask 앱을 띄우는 가장 단순한 형태다.
FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install flask
CMD ["python", "app.py"]
이 파일을 둔 폴더에서 다음 명령을 실행하면 이미지가 빌드되고 컨테이너가 실행된다.
docker build -t myapp .
docker run -p 8000:5000 myapp
여기서 -p 8000:5000 옵션은 호스트의 8000번 포트를 컨테이너의 5000번 포트로 연결한다는 의미다. 브라우저로 localhost:8000을 열면 컨테이너 안의 Flask 앱이 그대로 보인다. 제가 직접 이 흐름을 학교 발표 5분 전에 처음으로 끝까지 굴려 본 적이 있는데, "내 노트북·교실 데스크톱·교수님 노트북" 세 곳에서 모두 같은 한 줄로 동일한 결과를 띄우는 장면이 입문 단계에서 가장 강한 인상을 남겼다. Docker의 진짜 가치는 화려한 기능이 아니라 이 "어디서나 같다"는 단순한 약속이며, 다음 글에서는 여러 컨테이너를 묶어 띄우는 Docker Compose로 자연스럽게 이어진다.
태그: Docker, 컨테이너, 격리, 이미지, 네임스페이스, cgroups, 클라우드네이티브, DevOps
카테고리: 트렌드/클라우드
메타 디스크립션: Docker가 무엇이고 왜 등장했는지, 컨테이너 격리의 핵심인 네임스페이스와 cgroups, 그리고 이미지와 컨테이너의 관계를 첫 실행 예제와 함께 정리합니다.