클라우드 시대에도 애플리케이션 배포와 관리는 여전히 복잡했다. 2013년 등장한 도커(Docker)는 "어디서나 동일하게 실행되는 표준화된 소프트웨어 패키징"이라는 새로운 방식을 제시하며 등장했다. 2025년 현재는 전 세계 58.3% 이상의 기업이 프로덕션 환경에서 도커를 활용하고 있다고 한다.
개발자라면 "내 컴퓨터에서는 잘 돌아가는데..."라는 말을 한 번쯤 해본 경험이 있을 것이다. 도커는 이런 문제를 근본적으로 해결해준다.
1. 환경 일관성 보장
개발, 테스트, 운영 환경 간의 차이로 인한 문제 해소
"작동했는데 왜 안돼?"라는 소모적인 논쟁 종식
모든 팀원이 정확히 동일한 환경에서 작업 가능
2. 리소스 효율성
VM보다 가볍고 빠른 실행 환경 제공
호스트 시스템 자원을 더 효율적으로 활용
동일 하드웨어에서 더 많은 애플리케이션 실행 가능
3. 빠른 배포와 확장
애플리케이션 구성 요소를 독립적으로 패키징하여 배포 가능
필요에 따라 컨테이너를 빠르게 시작하거나 종료
CI/CD 파이프라인 통합 용이
컨테이너 가상화
도커의 컨테이너 기술은 리눅스 커널의 cgroups와 namespace 기능을 기반으로 구현된다고 한다. 전통적인 가상 머신(VM)이 하이퍼바이저를 통해 전체 운영체제를 가상화하는 반면, 도커 컨테이너는 호스트 커널을 공유하며 프로세스 수준의 격리를 제공한다. 덕분에 200MB 크기의 우분투 컨테이너가 전체 VM(보통 1GB 이상) 대비 80% 이상의 디스크 공간을 절약할 수 있다.
https://jhyonhyon.tistory.com/51

가상머신(VM): 하이퍼바이저를 통해 완전한 OS를 가상화
도커 컨테이너: 호스트 OS커널을 공유하며 프로세스 수준에서 격리
도커는 리눅스 커널의 cgroups와 namespace 기술을 활용해 프로세스를 격리하므로 VM보다 훨씬 효율적
┌────────────────────────────────────┐
│ 호스트 시스템 │
│ ┌───────────┐ ┌───────────┐ │
│ │ 컨테이너 A │ │ 컨테이너 B │ │
│ │ APP A │ │ APP B │ │
│ │ Libs │ │ Libs │ │
│ └───────────┘ └───────────┘ │
│ │ │ │
│ ┌─────────────────────────────┐ │
│ │ 도커 데몬 │ │
│ └─────────────────────────────┘ │
│ │ │ │
│ ┌─────────────────────────────┐ │
│ │ 호스트 OS │ │
│ └─────────────────────────────┘ │
└────────────────────────────────────┘
도커 데몬: 백그라운드에서 실행되는 서비스로 REST API를 통해 요청 처리
도커 클라이언트: 사용자가 명령어를 입력하는 인터페이스 (CLI)
이미지: 애플리케이션과 그 종속성을 포함한 읽기 전용 템플릿
컨테이너: 이미지의 실행 가능한 인스턴스
레지스트리: 이미지를 저장하고 공유하는 저장소 (ex: Docker Hub)

도커는 CI/CD 파이프라인을 크게 변화시켰다고 한다.
일례로 기존의 배포 시간을 45분에서 7분 이내로 단축시켰으며, Netflix와 같은 기업은 하루 500회 이상의 프로덕션 배포를 수행할 수 있게 되었다.
모놀리스 방식: 하나의 큰 애플리케이션에 모든 기능 포함
마이크로서비스 방식: 작은 독립 서비스들의 조합
도커 기반 마이크로서비스는 각 서비스를 독립적으로 확장할 수 있게 해줍니다. Uber의 경우 5,000개 이상의 도커 서비스가 Kubernetes 클러스터에서 운영되며, 트래픽 급증 시 필요한 서비스만 자동으로 확장된다.
각 운영체제별 설치 방법은 다음과 같다:
Ubuntu Linux
# 필요한 패키지 설치
sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
# Docker 공식 GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Docker 저장소 추가
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# Docker 설치
sudo apt-get update
sudo apt-get install docker-ce
# 사용자를 docker 그룹에 추가 (sudo 없이 실행하기 위함)
sudo usermod -aG docker $USER
macOS
Windows:
설치가 완료되면 다음 명령어로 도커가 제대로 설치되었는지 확인:
docker --version
docker run hello-world
# 이미지 검색
docker search nginx
# 이미지 다운로드
docker pull nginx
# 다운로드한 이미지 목록 확인
docker images
# 사용하지 않는 이미지 정리
docker image prune
# 컨테이너 실행
docker run -d -p 80:80 --name my-nginx nginx
# 실행 중인 컨테이너 목록 확인
docker ps
# 모든 컨테이너 목록 확인 (중지된 컨테이너 포함)
docker ps -a
# 컨테이너 로그 확인
docker logs my-nginx
# 컨테이너 중지
docker stop my-nginx
# 컨테이너 시작
docker start my-nginx
# 컨테이너 삭제 (중지 상태여야 함)
docker rm my-nginx
# 컨테이너 강제 삭제 (실행 중이어도 삭제)
docker rm -f my-nginx
이번에는 간단한 Node.js 웹 애플리케이션을 컨테이너화해보자.
mkdir docker-node-app
cd docker-node-app
npm init -y
npm install express
app.js 파일 생성:// app.js
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.send('안녕하세요! 도커로 실행 중인 Node.js 애플리케이션입니다.');
});
app.listen(PORT, () => {
console.log(`서버가 포트 ${PORT}에서 실행 중입니다.`);
});
Dockerfile 생성:FROM node:latest -alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
docker build -t my-node-app .
docker run -d -p 3000:3000 --name node-app-container my-node-app
http://localhost:3000으로 접속하여 확인여러 컨테이너를 함께 실행해야 하는 경우 Docker Compose를 활용하면 편리하다. 간단한 Node.js + MongoDB 애플리케이션을 예로 들어보자.
docker-compose.yml 파일 생성:version: '3'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- MONGO_URI=mongodb://mongo:27017/myapp
depends_on:
- mongo
mongo:
image: mongo
ports:
- "27017:27017"
volumes:
- mongo-data:/data/db
volumes:
mongo-data:
app.js 파일을 MongoDB 연결을 포함하도록 수정:const express = require('express');
const mongoose = require('mongoose');
const app = express();
const PORT = process.env.PORT || 3000;
const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/myapp';
mongoose.connect(MONGO_URI)
.then(() => console.log('MongoDB에 연결되었습니다.'))
.catch(err => console.error('MongoDB 연결 오류:', err));
app.get('/', (req, res) => {
res.send('도커 컴포즈로 실행 중인 Node.js + MongoDB 애플리케이션입니다.');
});
app.listen(PORT, () => {
console.log(`서버가 포트 ${PORT}에서 실행 중입니다.`);
});
npm install mongoose
docker-compose up -d
docker-compose down
# 멀티 스테이지 빌드 예시
FROM node:18 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
# 보안 강화 설정 예시
version: '3.8'
services:
web:
image: myapp:secure
user: "1000:1000" # 루트 권한 사용 방지
read_only: true # 파일시스템 변경 방지
security_opt:
- no-new-privileges # 권한 상승 방지
cap_drop:
- ALL # 모든 특수 권한 제거
이러한 보안 설정은 NIST SP 800-190 표준에 따라 컨테이너 취약점 발생률을 줄인다고 한다.
도커는 현재 개발자 중심 전략으로 Docker Desktop과 BuildKit에 집중하고 있다. 쿠버네티스가 점차 컨테이너 오케스트레이션 표준으로 자리잡았지만, 여전히 78%의 쿠버네티스 클러스터가 도커로 빌드된 이미지를 사용한다.
AWS Fargate, Google Cloud Run 등 서버리스 컨테이너 서비스가 연평균 150% 성장하고 있으며, 2025년에는 전체 컨테이너 워크로드의 40%를 차지할 전망이다. 인프라 관리 부담 없이 컨테이너 기반 애플리케이션을 실행할 수 있는 점이 제일 강력하다.
도커는 단순한 가상화 도구를 넘어 클라우드 네이티브 생태계의 핵심 인프라 1황이다. 2025년 현재 90% 이상의 포춘 500대 기업이 도커를 프로덕션에 사용하며, 컨테이너화된 워크로드의 68%가 Kubernetes와 연동되어 있다. 시장의 니즈와 편의성 때문에 도커 기반의 개발환경은 계속 커지지 않을까 싶다.