프로그래밍/DevOps

[DevOps] Docker 기초 — 컨테이너가 대체 뭔데? "내 컴퓨터에선 되는데요"의 종말

이슬먹는 개발자 2026. 7. 6. 12:03
728x90
반응형

개발하다 보면 한 번쯤 이 말을 하거나 듣게 된다.

"어? 제 컴퓨터에선 되는데요...?"

내 노트북에선 멀쩡히 돌아가던 코드가, 동료 컴퓨터나 서버에만 올리면 안 된다. 자바 버전이 달라서, 라이브러리가 없어서, OS가 달라서, 환경변수가 안 잡혀서... 이유는 매번 다르다. 이 지긋지긋한 문제를 뿌리부터 없애주는 게 바로 Docker다.

오늘은 Docker의 첫걸음으로, 컨테이너가 대체 뭔지 개념부터 잡아본다. 명령어 암기는 그 다음이다. 왜 필요한지를 알면 명령어는 자연스럽게 따라온다.


문제의 뿌리: "환경이 다르다"

방금 그 "내 컴퓨터에선 되는데요" 문제의 핵심은 하나다. 실행 환경이 다르기 때문이다.

내 프로그램 하나가 제대로 돌려면 사실 엄청나게 많은 게 맞아떨어져야 한다.

  • 특정 언어 런타임 (Node 18? 20? Python 3.11?)
  • 필요한 라이브러리와 그 버전들
  • OS와 시스템 패키지
  • 환경변수, 설정 파일

이걸 개발자마다, 서버마다 일일이 똑같이 맞추는 건 지옥이다. 하나라도 어긋나면 안 돈다. 그래서 사람들은 생각했다. "프로그램이랑 그 실행 환경을 통째로 묶어서 옮길 순 없을까?"

그게 바로 컨테이너의 아이디어다.


컨테이너 = 프로그램 + 실행 환경을 통째로 담은 상자

컨테이너(Container)는 내 프로그램과 그게 돌아가는 데 필요한 모든 것(런타임, 라이브러리, 설정)을 하나로 묶은 격리된 실행 단위다.

비유하자면 이렇다. 이사할 때 짐을 하나하나 손에 들고 옮기는 게 아니라, 컨테이너 박스에 다 넣어서 통째로 옮기는 것과 같다. 박스 안에 뭐가 어떻게 들었든, 박스만 옮기면 어디서든 똑같이 풀 수 있다.

그래서 컨테이너로 만들어두면 내 노트북이든, 동료 컴퓨터든, 클라우드 서버든 어디서 실행해도 똑같이 동작한다. "내 컴퓨터에선 되는데요"가 사라지는 거다.


그럼 가상머신(VM)이랑 뭐가 다른데?

"환경을 통째로 옮긴다"는 말을 들으면 가상머신(VM)을 떠올리는 사람도 있다. VM도 비슷한 걸 하니까. 근데 결정적인 차이가 있다.

가상머신(VM): 컴퓨터 위에 가상의 컴퓨터를 통째로 하나 더 만든다. 그 안에 OS(운영체제)까지 통째로 깔린다. 그래서 무겁고, 뜨는 데 오래 걸리고, 자원도 많이 먹는다.

컨테이너: OS는 호스트 것을 공유하고, 프로그램 실행에 필요한 부분만 격리한다. 그래서 훨씬 가볍고 빠르게 뜬다. 초 단위가 아니라 거의 순식간이다.

[ 가상머신 ]                    [ 컨테이너 ]

  앱 A     앱 B                   앱 A    앱 B
 ┌─────┐  ┌─────┐                ┌────┐  ┌────┐
 │ OS  │  │ OS  │   ← OS 통째    │    │  │    │  ← OS 공유
 └─────┘  └─────┘                └────┘  └────┘
 [하이퍼바이저]                   [ Docker 엔진 ]
 [   호스트 OS   ]                [   호스트 OS   ]
 [    하드웨어   ]                [    하드웨어   ]

핵심만 기억하자. VM은 집을 통째로 짓는 것, 컨테이너는 한 건물 안에서 방을 나눠 쓰는 것이다. 컨테이너가 훨씬 가볍다.


이미지와 컨테이너: 붕어빵 틀과 붕어빵

Docker를 배우면 이미지(Image)컨테이너(Container)라는 단어가 계속 나온다. 이 둘의 관계가 처음엔 헷갈리는데, 비유 하나면 끝난다.

  • 이미지 = 붕어빵 틀 (설계도)
  • 컨테이너 = 그 틀로 찍어낸 붕어빵 (실제로 돌아가는 것)

이미지는 "이런 환경에 이런 프로그램을 담아라"라고 정의해둔 설계도이자 템플릿이다. 그 자체로는 실행되지 않는다. 그냥 정지된 틀이다.

컨테이너는 그 이미지를 실제로 실행시킨 상태다. 틀(이미지) 하나로 붕어빵(컨테이너)을 여러 개 찍어낼 수 있듯이, 이미지 하나로 컨테이너를 여러 개 띄울 수 있다.

이미지 (틀)  →  실행(run)  →  컨테이너 (돌아가는 것)
                            →  컨테이너 2
                            →  컨테이너 3

정리하면, 이미지를 만들어두고(build), 그걸 실행해서 컨테이너로 띄운다(run). 이게 Docker의 기본 흐름이다.


손으로 한 번 느껴보기

개념만 보면 감이 안 오니까, 설치돼 있다고 치고 명령어 몇 개만 맛보자. (Docker 설치는 공식 사이트에서 Docker Desktop 받으면 된다.)

가장 유명한 첫 실행, hello-world다.

docker run hello-world

이 한 줄이 하는 일은 이렇다.

  1. hello-world 이미지가 내 컴퓨터에 있나 확인한다.
  2. 없으면 Docker Hub(이미지 저장소)에서 자동으로 내려받는다.
  3. 그 이미지로 컨테이너를 만들어 실행한다.
  4. 컨테이너가 인사말을 출력하고 종료된다.

진짜 웹서버도 한 줄이면 띄운다. nginx를 예로 들면,

docker run -d -p 8080:80 nginx
  • -d : 백그라운드로 실행 (detached)
  • -p 8080:80 : 내 컴퓨터 8080 포트를 컨테이너의 80 포트에 연결
  • nginx : 사용할 이미지 이름

이러면 브라우저에서 localhost:8080 들어갔을 때 nginx 기본 페이지가 뜬다. 내 컴퓨터에 nginx를 직접 설치한 적도 없는데 말이다. 이미지 안에 이미 다 들어있으니까.

지금 떠 있는 컨테이너 목록은 이걸로 본다.

docker ps

자주 쓰는 명령어 미리보기

지금 다 외울 필요는 없고, "이런 게 있구나" 정도만 훑어두자.

명령어 하는 일
docker pull 이미지 이미지 내려받기
docker run 이미지 이미지로 컨테이너 실행
docker ps 실행 중인 컨테이너 목록
docker ps -a 종료된 것까지 전체 목록
docker stop 컨테이너 컨테이너 멈추기
docker images 내가 가진 이미지 목록
docker rm / rmi 컨테이너 / 이미지 삭제

정리

오늘은 Docker의 명령어보다 왜 쓰는지, 무슨 개념인지에 집중했다. 핵심만 다시 정리하면 이렇다.

  • Docker는 "내 컴퓨터에선 되는데요" 문제를 없애준다. 프로그램과 실행 환경을 통째로 묶어서 어디서든 똑같이 돌게 하니까.
  • 컨테이너는 프로그램 + 실행 환경을 담은 가볍고 격리된 실행 단위다.
  • VM과 달리 OS를 공유해서 훨씬 가볍고 빠르다.
  • 이미지는 붕어빵 틀(설계도), 컨테이너는 그걸로 찍어낸 붕어빵(실행 상태)이다.

이 개념만 잡혀 있으면 이제 뭘 배워도 흔들리지 않는다. 다음 글에서는 직접 내 프로젝트를 이미지로 만드는 Dockerfile 작성법을 다뤄보자. 남이 만든 이미지를 쓰는 걸 넘어, 내 앱을 컨테이너로 만드는 진짜 첫걸음이다.

728x90
반응형