개발하다 보면 한 번쯤 이 말을 하거나 듣게 된다.
"어? 제 컴퓨터에선 되는데요...?"
내 노트북에선 멀쩡히 돌아가던 코드가, 동료 컴퓨터나 서버에만 올리면 안 된다. 자바 버전이 달라서, 라이브러리가 없어서, 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
이 한 줄이 하는 일은 이렇다.
hello-world이미지가 내 컴퓨터에 있나 확인한다.- 없으면 Docker Hub(이미지 저장소)에서 자동으로 내려받는다.
- 그 이미지로 컨테이너를 만들어 실행한다.
- 컨테이너가 인사말을 출력하고 종료된다.
진짜 웹서버도 한 줄이면 띄운다. 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 작성법을 다뤄보자. 남이 만든 이미지를 쓰는 걸 넘어, 내 앱을 컨테이너로 만드는 진짜 첫걸음이다.
'프로그래밍 > DevOps' 카테고리의 다른 글
| [DevOps] Docker Compose — 여러 컨테이너를 한 번에 관리하기 (0) | 2026.07.09 |
|---|---|
| [DevOps] Dockerfile 작성법 — 내 앱을 직접 이미지로 만들기 (0) | 2026.07.07 |