1. 가상화
1-1. 가상화란
호스트 하나의 물리 자원을 나눠서 여러 독립된 환경처럼 쓰는 기술이다. 이 슬라이드는 그 앞에 에뮬레이션이라는 비슷하지만 다른 개념을 나란히 놓고 비교한다.
| 에뮬레이션 | 호스트와 다른 CPU 아키텍처의 모든 동작·명령어를 흉내 내서 처리 | 명령어를 하나하나 소프트웨어로 번역 | 느림 🐢 |
| 가상화 | 가상 OS가 드라이버를 통해 호스트 자원을 스케줄링해 나눠 씀 | 실제 자원을 쪼개서 배분 | 빠름 ⚡ |
에뮬레이션 (Emulation)
호스트 시스템의 아키텍처와 다른 CPU의 모든 동작 및 명령어를 모방하여 처리하는 기술이다. x86 위에서 ARM용 프로그램을 돌리듯, 다른 하드웨어를 소프트웨어로 재현한다.
QEMU (a generic open source machine emulator)
└─ Cisco ASA, PIX, IPS 구동
→ Cisco 보안 장비가 없어도 그 동작을 그대로 재현할 수 있다는 뜻이다.
가상화 (Virtualization)
가상의 OS가 드라이버들을 통해 호스트 시스템의 하드웨어 자원을 스케줄링하여, 여러 환경이 서로 나누어 사용하는 기술이다.
성능 차이의 이유
에뮬레이션 → CPU 명령어를 통째로 번역 → 오버헤드 큼 → 느림
가상화 → 호스트 자원을 그대로 분할 → 오버헤드 작음 → 빠름
→ 그래서 호스트 자원을 분할해 쓰는 가상화가 에뮬레이션보다 빠르다.
가상화 장점
| 비용 절감 | 서버 한 대에 여러 환경을 올려 물리 장비 구매비 절감 |
| 간단한 배포 (simplest deployment) | 새 환경을 필요할 때 빠르게 찍어냄 |
| 관리 비용(시간) 절감 (save management time costs) | 개별 관리 대신 한곳에서 통합 관리 |
1-2. QEMU
거의 완벽에 가까운 오픈소스 에뮬레이터로, 앞 슬라이드에서 나온"다른 CPU를 흉내 내는 기술의 대표 주자다.
가장 큰 특징: 동적 변환 (Dynamic Translation)
Guest CPU 명령어 → [실행 중 실시간 변환] → Host CPU 명령어
Guest CPU를 위한 명령어를 실행 중에 Host CPU용 명령어로 바꿔주는 기능이다. 이 덕분에 이식성(portability)이 매우 높아서 대부분의 하드웨어 플랫폼을 지원한다.
지원 플랫폼: x86 · PowerPC · PowerMac · ARM · SPARC 등
에뮬레이션 대상 — 사실상 모든 H/W
| 연산 | CPU |
| 저장 | CD-ROM/DVD, FDD, HDD |
| 입출력 | Video, NIC, Sound |
| 버스·슬롯 | PCI, ISA |
| 포트 | PS/2, Parallel-Port, Serial-Interface, USB |
→ CPU부터 주변장치까지 거의 모든 하드웨어를 에뮬레이팅한다.
다른 가상화 기술의 기반이 됨
이런 장점 때문에, 다른 유명 가상화 솔루션들도 각자에 맞게 수정한 QEMU를 가져다 쓴다.
KVM ┐
Xen (HVM) ├─→ 수정된 QEMU 사용
VirtualBox ┘
→ QEMU가 단독 도구를 넘어 가상화 생태계의 공용 부품 역할을 한다는 뜻이다.
관련 도구 두 가지
| qemu-img | VM에 쓸 가상 하드디스크 이미지(VDI)를 생성 / 삭제 / 스냅샷 / 변환 |
| qemu-kvm | QEMU + KVM 결합 — 하드웨어 가속을 받아 성능을 끌어올린 실행 방식 |
1-3. Hypervisor based
Hypervisor based
하이퍼바이저는 가상 머신을 만들고 관리하는 소프트웨어 계층이다. 이 계층이 하드웨어 바로 위에 오느냐, OS 위에 오느냐에 따라 Type-1과 Type-2로 나뉜다.
| 구분 | Type-1 | Type-2 |
| 별칭 | native / bare-metal | hosted |
| 실행 위치 | 하드웨어 바로 위 | 호스트 OS 위 |
| 계층 구조 | HW → 하이퍼바이저 → Guest OS | HW → 호스트 OS → 하이퍼바이저 → Guest OS |
| 성능 | 빠름 ⚡ (중간 OS 없음) | 상대적으로 느림 🐢 (OS 한 겹 더) |
| 용도 | 서버·데이터센터 | 개인 PC·테스트 |
Type-1: Native / Bare-metal Hypervisor
호스트 하드웨어에서 직접 실행되어 하드웨어를 제어하고 게스트 운영체제를 관리하는 방식이다. 중간에 호스트 OS가 끼지 않는 게 핵심이다.
┌─────────────────┐
│ Guest OS │ ← 가상 머신
├─────────────────┤
│ HYPERVISOR │ ← 하드웨어를 직접 제어
├─────────────────┤
│ HARDWARE │
└─────────────────┘
TYPE 1
(native / bare-metal)
역사·제품:
- IBM이 1960년대에 개발한 최초의 하이퍼바이저가 바로 이 네이티브 방식이었다.
- 현대 제품: Oracle VM Server for SPARC / x86 · Citrix XenServer · VMware ESX/ESXi · Microsoft Hyper-V 2008/2012
Type-2: Hosted Hypervisor
하드웨어 위에 호스트 OS가 먼저 깔리고, 그 위에서 하이퍼바이저가 앱처럼 돌아간다.
┌─────────────────┐
│ Guest OS │
├─────────────────┤
│ HYPERVISOR │ ← 호스트 OS 위에서 실행
├─────────────────┤
│ Host OS │ ← 한 겹 더 있음
├─────────────────┤
│ HARDWARE │
└─────────────────┘
TYPE 2
(hosted)
→ VirtualBox, VMware Workstation 같은 개인용 툴이 여기 해당한다.
- Type-1 (bare-metal) = 하드웨어 위에서 직접 실행 → 중간 OS 없음 → 빠름, 서버용
- Type-2 (hosted) = 호스트 OS 위에서 실행 → OS 한 겹 더 → 상대적으로 느림, 개인용
1-4. 가상화 모드
가상머신의 os를 게스트 os라고 한다
가상화 모드
가상화를 구현하는 방식은 크게 전가상화(Full)와 반가상화(Para) 두 가지로 나뉜다. 차이의 핵심은 Guest OS를 고쳐야 하느냐다.
| 구분 | 전가상화 (Full) | 반가상화 (Para) |
| 별칭 | Native Virtualization | — |
| Guest OS 수정 | 불필요 (수정 없이 실행) | 필요 (커널 일부 수정) |
| 하드웨어 인식 | OS가 하드웨어를 직접 제어한다고 착각 | 자신이 가상화됐음을 인지 |
| 명령어 처리 | 하이퍼바이저가 중재·번역(translation) | 제어 코드를 OS에 심어 직접 요청 |
| 성능 | 낮음 🐢 (중재 오버헤드) | 높음 ⚡ (번역 불필요) |
| CPU 지원 | 가상화 지원 기능 필수 (Intel VT / AMD-V) | 상대적 자유 |
| 사용 가능 OS | 대부분의 OS | 오픈소스(Linux 등)만 |
| 제품 | VMware ESX, MS Hyper-V | Xen 등 |
1) 전가상화 (Full-Virtualization)
Guest OS와 하드웨어 사이를 중재하는 가상 머신을 이용하는 방식이다.
Guest OS → "내가 하드웨어를 직접 제어한다!" (착각)
실제로는 ↓
VMM(하이퍼바이저)가 중간에서 명령어를 받아 에뮬레이션
- 하드웨어에 의존적인 특정 명령어는 VMM(하이퍼바이저) 안에서 핸들링한다.
- 하이퍼바이저가 중재하기 때문에 실제 하드웨어보다 성능이 낮다.
- OS를 수정 없이 그대로 실행할 수 있는 게 최대 장점이다.
- 단, 이를 실현하려면 물리적인 '가상화 지원 기능'(Intel VT / AMD-V)이 반드시 있어야 한다.
- OS는 하드웨어를 직접 제어한다고 인식하지만, 실제로는 하드웨어단의 하이퍼바이저를 통해 에뮬레이션된다.
- 제품: VMware ESX · MS Hyper-V

2) 반가상화 (Para-Virtualization)
전가상화처럼 하이퍼바이저가 공유 자원을 중재하지만, 제어 코드를 Guest OS에 심어줘야 한다는 제약이 있는 방식이다.
Guest OS (커널 수정됨) → "나 가상화된 거 알아. 하드웨어 좀 써줘"
↓ (직접 요청)
하이퍼바이저 → 곧바로 하드웨어에 전달
- 전가상화와 달리 translation(번역)이 필요 없어 속도 면에서 이점이 있다.
- 하드웨어를 완전히 가상화하지 않아, OS 입장에서는 자신이 직접 하드웨어를 제어하는 것과 비슷한 구성이 된다.
- 구조적으로 OS가 하이퍼바이저에 하드웨어 제어 명령을 요청하면, 하이퍼바이저가 이를 곧바로 하드웨어에 알린다. → 직접 연결을 요청하는 방식이라 가상화되지 않은 실제 시스템에 가까운 성능을 낸다.
- 단, Guest OS로 쓰려면 커널 일부를 수정해 하이퍼바이저 기능을 쓰도록 바꿔야 한다. → 그래서 커널 수정이 가능한 Linux 같은 오픈소스 OS에서만 사용 가능하다.


kvm은 리눅스 커널 자체를 하이퍼바이저로 바꿔주는 가상화 기술
Xen vs KVM 비교
| 구분 | XEN | KVM |
| 유형 | Type-1 (bare-metal) | 리눅스 커널에 얹힘 (Type-1로 분류) |
| 하드웨어 제어 주체 | 별도 관리 VM Dom0 | Host OS(리눅스) 직접 |
| 드라이버 | Dom0가 따로 보유 | 리눅스 기존 드라이버 재사용 |
| 기반 | 자체 하이퍼바이저 | 리눅스 커널 모듈 + QEMU |
1-5. VM Snapshots
Raw vs. Qcow2 (KVM)
VM의 가상 디스크를 저장하는 파일 포맷 이야기다. 앞에서 qemu-img가 가상 디스크 이미지를 생성/스냅샷/변환한다고 했는데, 그 이미지의 대표 포맷 두 가지가 바로 Raw와 Qcow2다.
| r구분 | Raw | Qcow2 (QEMU Copy-On-Write 2) |
| 디스크 할당 | VM 생성 전 미리 전체 할당 (고정) | 필요한 만큼 동적 할당 (dynamic provisioning) |
| 공간 효율 | 낮음 (안 써도 다 차지) | 높음 (쓴 만큼만 사용) |
| I/O 성능 | 빠름 ⚡ (미리 할당돼 있어 유리) | 상대적으로 느림 🐢 |
| Snapshot | ❌ 불가 | ✅ 가능 |
| Compression(압축) | ❌ | ✅ 가능 |
| Encryption(암호화) | ❌ | ✅ 가능 |
→ 핵심 트레이드오프: Raw는 성능, Qcow2는 기능·효율.
1) Raw
- VM 생성 전에 디스크 공간을 미리 통째로 할당해 둔다.
- 이미 자리를 잡아놨기 때문에 Qcow2보다 뛰어난 I/O 성능을 보인다.
- 대신 스냅샷·압축·암호화 같은 부가 기능은 지원하지 않는다.
2) Qcow2 (copy-on-write)
copy-on-write = "쓸 때 복사"
→ 원본은 그대로 두고, 변경분만 따로 기록
→ 그래서 snapshot(특정 시점 저장)이 자연스럽게 가능
- snapshot / compression / encryption 모두 지원한다.
- dynamic provisioning 지원 → VM이 요구하는 만큼만 공간을 할당해 효율적이다.
3) Snapshot의 의미
Snapshot = 일종의 "Backup"
→ 특정 시점의 VM 상태를 저장해 두고,
문제 생기면 그 시점으로 되돌릴 수 있음
주의할 점
- Libvirt snapshot은 특정 파일 포맷에서만 가능하다. → 즉 아무 포맷이나 되는 게 아니라, 스냅샷을 지원하는 Qcow2에서만 제대로 쓸 수 있다. Raw로는 libvirt 스냅샷을 못 잡는다.
1-6. VM Migration

1) VM Migration
실행 중이거나 저장된 VM을 한 호스트에서 다른 호스트로 옮기는 기술이다. VM이 파일 형태로 존재하기 때문에(앞의 Qcow2/Raw 이미지) 물리 서버를 옮기는 것과 달리 통째로 이사시킬 수 있다.
2) Requirements (전제 조건)
마이그레이션이 되려면 두 호스트 환경이 거의 쌍둥이처럼 맞춰져 있어야 한다.
| 조건 | 내용 | 필요한 이유 |
| 온라인 연결 | 최소 두 대의 호스트가 온라인으로 연결, 게스트 설치됨 | 옮길 곳과 받을 곳이 실시간으로 붙어 있어야 함 |
| 공유 스토리지 | NFS, GFS2, iSCSI, FC 등 공유 네트워크 저장 장치 | VM 디스크를 양쪽이 함께 봐야 통째로 복사 안 해도 됨 |
| 동일 OS 환경 | 동일 OS · 동일 버전 · 동일 업데이트 상태 | 옮긴 뒤 호환성 깨지지 않게 |
| 포트 개방 | 막히지 않은 포트 | 마이그레이션 통신 경로 확보 |
| 동일 네트워크 | 동일한 브릿지 및 네트워크 설정 | 옮겨가도 네트워크 그대로 붙게 |
| 동일 마운트 | 마운트 위치 및 디렉터리 일치 | VM이 참조하는 경로가 양쪽 동일해야 함 |
→ 양쪽 호스트를 최대한 똑같이 세팅하고, 디스크는 공유 스토리지에 둬야한다.
3) 왜 공유 스토리지가 중요한가
[공유 스토리지 있음]
Host A ─┐
├─ 공유 스토리지(VM 디스크) ← 디스크는 그대로 두고
Host B ─┘ 메모리 상태만 옮기면 됨 → 빠름 ⚡
[공유 스토리지 없음]
Host A ──(디스크 통째로 네트워크 복사)──> Host B → 느림 🐢
4) 마이그레이션의 이점
| Load Balancing | 특정 호스트에 부하 몰리면 다른 호스트로 VM을 옮겨 분산 |
| Failover | 호스트에 장애 나기 전/후 다른 호스트로 넘겨 서비스 지속 |
| 에너지 절감 | VM을 소수 호스트로 몰아 담고, 빈 서버는 꺼서 전력 절약 |
| Geographic Migration | 지리적으로 떨어진 데이터센터 간 이전 (재해 대비·위치 최적화) |
1-7. 가상화와 컨테이너


⭐ 가상화(VM) vs 컨테이너
- 가상 머신(VM): 하이퍼바이저를 통해 물리 하드웨어를 가상화하며, 각 VM마다 개별 운영체제(Guest OS)를 실행한다.
- 컨테이너: 호스트 운영체제의 커널을 공유하며, 애플리케이션 구동에 필요한 라이브러리만 격리해 실행하므로 별도의 Guest OS가 없다.
| 항목 | Virtual Machine | Container |
| Instances/PM(물리 서버당 인스턴스 수) | low density (적게 올림) | high density (많이 올림) |
| Isolation level (격리 수준) | complete isolation (완전 격리) | process level — namespace / cgroups로 프로세스 단위 격리 |
| Kernel | Hypervisor 기반, 자기만의 가상 자원과 OS 보유 | Docker 호스트와 커널 공유 |
| Instance Networking | virtual/physical switch와 연결 | own network stack + IPC (signals, sockets, pipes…) |
1) Instances/PM — 밀도
VM : 무거움 → 물리 서버 1대에 몇 개만 (low density)
컨테이너 : 가벼움 → 물리 서버 1대에 수십~수백 개 (high density)
→ 커널을 안 올리는 컨테이너가 같은 하드웨어에 훨씬 촘촘하게 들어간다.
2) Isolation level — 격리 수준
| vm | 컨테이너 |
| 완전 격리 — 커널까지 따로라 서로 완전히 분리 | 프로세스 수준 격리 — 커널은 공유하되 namespace, cgroups로 구분 |
namespace = "무엇을 볼 수 있나" 격리 (프로세스·네트워크·파일시스템 시야 분리)
cgroups = "얼마나 쓸 수 있나" 제한 (CPU·메모리 자원 할당)
→ 컨테이너는 이 두 리눅스 커널 기능으로 격리를 흉내 낸다. 그래서 VM만큼 완벽하진 않지만 실용적인 분리가 된다.
3) Kernel — 핵심 차이
VM : 하이퍼바이저 위에 자기 OS·커널을 통째로 → 독립적
컨테이너 : 호스트(Docker host)의 커널을 그대로 공유 → 종속적
4) Instance Networking — 네트워킹
| VM | 컨테이너 |
| 가상/물리 스위치에 연결되는 방식 | 자체 네트워크 스택을 갖고 IPC로 통신 |
2. Cloud Computing과 서비스 개요
2-1. 클라우드 컴퓨팅


Cloud Native Application 특성 이해
클라우드 환경에 최적화되도록 설계·운영하는 애플리케이션 방식이다
핵심 구성 요소 정리
| 요소 | 의미 | 역할 |
| MicroService (MSA) | 큰 앱을 작은 독립 서비스로 쪼갬 | 클라우드 네이티브의 중심 축 |
| Container | 각 마이크로서비스를 담는 실행 단위 | 가볍고 이식성 높은 배포 |
| Decouple | 서비스 간 결합도를 낮춤(느슨한 연결) | 하나 고장나도 전체 영향 최소화 |
| REST/HTTP API | 서비스끼리 통신하는 표준 방식 | MSA 간 데이터 주고받기 |
| Serverless | 서버 관리 없이 함수 단위 실행 | 필요할 때만 실행 → 비용·운영 절감 |
| DevOps | 개발 + 운영 통합 문화 | 빠른 개발-배포 사이클 |
| CI/CD | 지속적 통합/배포 자동화 | 코드 → 빌드 → 배포 파이프라인 |
| IaC (Infra as Code) | 인프라를 코드로 관리 | 인프라 자동 구성·재현 |
1. 앱을 쪼갠다 → MicroService
2. 각각을 담는다 → Container
3. 느슨하게 연결한다 → Decouple + REST/HTTP API
4. 자동으로 배포한다 → DevOps → CI/CD → K8s
5. 인프라도 코드로 → IaC (Ansible / Terraform)
3-Tier + MSA 트래픽 흐름
Client → LB(로드밸런서) → WAF(방화벽) → 여러 MicroService
→ 3 Tier 구조(웹 - 앱 - DB 계층 분리)
클라이언트 요청이 로드밸런서와 방화벽(WAF)을 거쳐 잘게 나뉜 마이크로서비스들로 분산되는, 실제 클라우드 서비스의 트래픽 경로
IaC 도구
IaC = Ansible + Terraform (+ SaltStack 계열)
• Ansible : 구성 관리 (서버에 뭘 설치/설정할지)
• Terraform : 인프라 프로비저닝 (서버·네트워크 자체를 코드로 생성)
3. 도커 기본 기술 이해
3-1. 컨테이너(Container) 종합 정리
| 유형 | 시스템 컨테이너 + 애플리케이션 컨테이너 |
| 격리 방식 | OS-level isolation — 커널 기능을 개별적으로 격리 |
| 자원 통제 | cgroup (Control Group)으로 resource 할당·통제 |
| 패키징 | App 실행에 필요한 사용자 정보 + Library/binary set 포함 |
| 분할 유형 | Horizontal partition (수평 분할) |
| 주 목적 | Application을 빠르게 배포 |
| 성능 | Baremetal(물리 서버)과 거의 동일 ⚡ |
| 제품 | Solaris Zone, FreeBSD Jails, OpenVZ, LXC, Docker |
1) OS-level isolation (OS 수준 격리)
커널 기능을 항목별로 쪼개서 격리:
• filesystem → 파일시스템 시야 분리
• process table → 프로세스 목록 분리
• network namespace → 네트워크 환경 분리
2) cgroup (Control Group)
cgroup = "얼마나 쓸 수 있나" 통제
→ CPU, 메모리 등 resource를 컨테이너별로 할당·제한
특징
- App 실행환경 패키징: 컨테이너 안에 앱뿐 아니라 필요한 사용자 정보 + 라이브러리/바이너리까지 함께 담는다. → 그래서 어디에 옮겨도 똑같이 돈다(이식성).
- Horizontal partition (수평 분할): 하나를 여러 개로 나란히 늘리는 방식. → 부하가 늘면 컨테이너를 옆으로 복제해서 확장(scale-out)하기 좋다.
- 빠른 배포: 커널을 공유해 가볍기 때문에 띄우고 지우는 속도가 빠르다. → 클라우드 네이티브·MSA와 잘 맞는 이유.
- Baremetal급 성능: VM처럼 하이퍼바이저 중재나 커널 중복이 없어, 물리 서버와 거의 같은 성능을 낸다.
- process group 독립 관리: 프로세스 그룹을 서로 간섭 없이 독립적으로 관리하는 게 목적.
3-2. 컨테이너(Container) 유형
컨테이너는 담는 범위에 따라 두 가지 유형으로 나뉜다. 하나의 프로세스만 담는 애플리케이션 컨테이너와, OS처럼 여러 프로세스를 통째로 담는 시스템 컨테이너다.
| System Container | Application Container | |
| 담는 범위 | init(systemd) + 여러 프로세스 | 단일 프로세스(앱) 하나 |
| 비유 | 경량 VM처럼 작은 OS 한 대 | 앱 하나만 돌리는 상자 |
| 그림 속 예시 | systemd, sshd, httpd 묶음 | named 하나 |
| 대표 기술 | LXC / LXD | Docker |
| 용도 | OS 환경 전체가 필요할 때 | 마이크로서비스 하나 배포 |

┌─ VM ──────────────────────────────────┐
│ ┌─ System Container ──────────────┐ │
│ │ sshd httpd │ │
│ │ ↘ ↗ ┌─ App Container ┐│ │
│ │ systemd │ named ││ │ ← 앱 컨테이너는
│ │ (init 역할) └───────────────┘│ │ 시스템 컨테이너 안에도
│ └──────────────────────────────────┘ │ 들어갈 수 있음
│ ┌──────────────────────────────────┐ │
│ │ kernel │ │ ← 공유
│ └──────────────────────────────────┘ │
└──────────────────────────────────────┘
Host H/W
System Container (시스템 컨테이너)
systemd (init 프로세스)
├─ sshd (원격 접속)
└─ httpd (웹 서버)
- systemd 같은 init을 최상위로 두고, 그 아래 sshd·httpd 등 여러 서비스를 함께 돌린다.
- 부팅부터 여러 데몬 관리까지 → 거의 하나의 작은 OS처럼 동작한다.
- VM과 비슷해 보이지만, 커널은 호스트와 공유한다는 점이 다르다. (앞에서 배운 컨테이너의 본질 그대로)
- 대표: LXC / LXD
Application Container (애플리케이션 컨테이너)
named (프로세스 하나만)
- 한 컨테이너 = 한 프로세스(앱) 원칙 → 마이크로서비스 배포에 최적.
- 가볍고 빠르게 띄웠다 지웠다 하기 좋다.
- 대표: Docker
System Container = systemd+ 여러 프로세스 → 작은 OS처럼, LXC/LXD
Application Container = 프로세스 하나만 → 마이크로서비스용, Docker
3-3. Docker란?
Docker 특징
| 이미지 관리 | 이미지 생성·배포 특화 | 컨테이너를 이미지로 찍어 쉽게 배포 |
| 이미지 버전 관리 | 태그로 버전 추적·롤백 | |
| Docker Hub 제공 | 중앙 개인/공개 저장소 (유/무료) | |
| 운영 이점 | 개발·서버 운영에 유용 | 개발-배포 환경 일치 |
| 이식성 뛰어남 | 어디서든 동일하게 실행 | |
| 보안 | Immutable Infrastructure | 서버 정보 유출·피해 최소화 |
| Namespace / cgroup 격리 | 프로세스·자원 분리 | |
| File system protection | 읽기 전용·권한 분리 |
1) 이미지 관리
이미지 생성 → 버전 태깅 → Docker Hub에 push → 어디서든 pull
- 이미지 생성·배포에 특화: 컨테이너 상태를 이미지로 굳혀서 배포한다.
- 버전 관리: 이미지에 태그(v1, v2…)를 붙여 추적·롤백이 쉽다.
- Docker Hub: 이미지를 올리고 받는 중앙 저장소. 개인/공개, 유료/무료 모두 지원.
2) 운영 이점 — 이식성 & Immutable Infrastructure
이식성(Portability)
내 노트북에서 되던 게 → 테스트 서버 → 운영 서버 어디서든 그대로
("It works on my machine" 문제 해결)
Immutable Infrastructure (불변 인프라)
기존: 서버에 직접 접속해서 고치고 패치 → 서버마다 상태 제각각
Docker: 서버는 안 건드림. 바꿀 게 있으면 이미지를 새로 만들어 통째 교체
→ 실행 중인 서버를 직접 수정하지 않으니 서버 정보 유출·설정 오염·장애 피해가 최소화된다. 이게 보안·안정성의 핵심 개념이다.
3) Namespace — 격리 영역
Docker가 리눅스 커널의 namespace로 격리하는 항목들
• process → 프로세스 목록 분리
• network → 네트워크 스택 분리
• mount → 파일시스템 마운트 분리
• hostname → 호스트명 분리
• shared memory → 공유 메모리 분리
→ 앞에서 배운 namespace의 실제 격리 대상 목록이다.
4) File System 보호
| read-only filesystem | 컨테이너 파일시스템을 읽기 전용으로 → 변조 방지 |
| Copy-on-Write (CoW) | 변경분만 따로 기록 (Qcow2에서 봤던 그 개념) → 저장 효율 ↑ |
| AuFS (Advanced Multi-layered Unification FS) | 여러 레이어를 겹쳐 하나로 보이게 → 이미지 레이어링의 기반 |
AuFS 레이어 구조:
[앱 레이어] ← 내가 추가한 것
[라이브러리 레이어] ← 공통, 재사용
[베이스 OS 레이어] ← 공통, 재사용
→ 겹치는 레이어는 공유해서 용량 절약
5) Privileged / Unprivileged Processes
Privileged : 호스트 권한까지 가진 프로세스 (강력하지만 위험)
Unprivileged : 제한된 권한만 (안전, 권장)
→ 컨테이너 프로세스의 권한 수준을 구분해 보안을 관리한다.

3-4. Docker 아키텍처
Docker의 동작 원리를 보여주는 구조도다. Client → Docker Host → Registry 3덩어리로 나뉜다.
| Client | 명령 입력 (docker build/pull/run) |
| Docker Host | Docker daemon이 실제 작업 수행, 이미지·컨테이너 보관 |
| Registry | 이미지 저장소 (Docker Hub 등) |
→ 핵심은 Docker daemon. Client는 명령만 내리고, 실제 일(이미지 받기·빌드·컨테이너 실행)은 전부 daemon이 한다.
① docker pull : Registry ──→ Host의 Images (이미지 받기)
② docker build : Dockerfile ─→ Host의 Images (이미지 만들기)
③ docker run : Images ────→ Containers (컨테이너 실행)
1) Image vs Container
Image : 실행 안 된 "틀" (붕어빵 틀)
Container : 이미지를 실행한 "실체" (구워진 붕어빵)
docker run → 이미지에서 컨테이너를 찍어냄
2) Docker 관리 대상과 CLI 구조
앞의 아키텍처에서 본 Docker daemon(server)이 실제로 관리하는 4가지 오브젝트와, 각각을 다루는 명령어를 정리한 그림이다.
Client (docker CLI)
↓ 명령 전달
REST API
↓
Server (docker daemon) ← 실제로 4대 오브젝트를 manage
3) Docker daemon이 관리하는 4대 오브젝트
| Container | 실행 중인 실체 | docker run, docker ps, docker rm |
| Image | 실행 틀(템플릿) | docker build, docker images, docker rmi |
| Network | 컨테이너 간 통신망 | docker network create/ls/rm |
| Data Volumes | 데이터 영구 저장소 | docker volume create/ls/rm |
4개 모두 manages로 daemon에 연결돼 있다. daemon이 이 넷을 전부 생성,조회,삭제한다.

3-5. Docker Client/Server 구조
Docker는 Client와 Server(daemon)가 분리된 구조로 동작한다. 사용자가 명령을 내리면 그게 어떻게 처리돼 결과로 돌아오는지 3단계로 보여주는 그림이다.
1. Client: $ docker run xxx
↓ (명령 전달)
2. Host: docker daemon → 컨테이너 생성·실행
↓
3. Client: output... (결과 반환)
| 1 | Client가 docker run 명령을 daemon에 전달 |
| 2 | Host의 daemon이 명령을 받아 컨테이너 실행 |
| 3 | 실행 결과(output)를 Client로 반환 |
- Client ≠ Server: 명령 내리는 곳(Client)과 실제 일하는 곳(daemon)이 분리돼 있다.
- 이 분리 덕분에 원격 제어도 가능하다 → 로컬 CLI로 다른 서버의 daemon을 조종할 수 있다.
- 사용자는 daemon 내부 동작을 몰라도 명령만 내리면 결과를 받는다.


3-6. docker.service 설정 — 원격 접속 활성화
/usr/lib/systemd/system/docker.service 파일을 편집하는 화면이다. 핵심은 ExecStart 줄에 -H tcp:// 옵션을 추가해서, 앞에서 배운 Client가 원격 daemon을 제어하는 걸 실제로 가능하게 만드는 작업이다.
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H fd:// --containerd=/run/containerd/containerd.sock
| /usr/bin/dockerd | Docker daemon 실행 파일 |
| -H tcp://0.0.0.0:2375 | TCP 2375 포트로 원격 접속 허용 (핵심 추가분) |
| -H fd:// | 기존 로컬 소켓 접속 유지 |
| --containerd=...sock | 컨테이너 런타임(containerd) 연결 |
→ -H tcp://0.0.0.0:2375 이 한 줄이 원격에서 이 daemon을 조종할 수 있게 열어주는 것이다. 0.0.0.0은 모든 IP에서 접속 허용, 2375는 Docker 표준 원격 포트다.

설정 후 적용 순서
systemctl daemon-reload # 바뀐 service 파일 반영
systemctl restart docker # daemon 재시작
🛑원격 Docker 접속 에러 — 호스트 이름을 못 찾음
앞에서 연 원격 포트(2375)로 실제 접속을 시도했는데 에러가 났다. 방화벽은 열렸지만 s1이라는 이름을 IP로 변환하지 못한 게 원인이다.
1) 실행한 명령과 결과
① firewall-cmd --add-port=2375/tcp --permanent
→ success 방화벽 2375 포트 개방 성공
② sudo docker -H s1:2375 run -d nginx
→ failed to connect... lookup s1 on 192.168.120.2:53: no such host
2) 에러 원인 분석
lookup s1 ... no such host
↑
"s1"이 뭔지 몰라서 IP로 못 바꿈 (DNS 조회 실패)
| 핵심 원인 | s1이라는 호스트 이름을 IP로 변환(name resolution) 실패 |
| DNS 서버(192.168.120.2:53)에 물어봤지만 | s1에 대한 등록 정보가 없음 |
| 방화벽은? | success → 포트는 정상적으로 열림 (방화벽 문제 아님) |
→ 즉 연결 자체를 시도하기도 전에, 목적지 주소를 못 찾아서 실패한 것이다. Docker 설정이나 포트 문제가 아니라 이름 해석 문제다.
3)💡해결 방법
방법 1 — IP 직접 사용 (가장 확실)
sudo docker -H 192.168.120.x:2375 run -d nginx
↑ s1의 실제 IP를 직접 입력
방법 2 — /etc/hosts에 등록
# /etc/hosts 파일에 추가
192.168.120.x s1
→ 이러면 s1을 해당 IP로 인식한다. 그 다음 원래 명령을 그대로 쓰면 된다.
firewall-cmd ... --permanent → 재적용 필요!
- --permanent는 영구 설정이지만 즉시 적용은 안 된다. 지금 세션엔 반영이 안 돼 있을 수 있다.
- 이름 문제를 고친 뒤에도 접속이 안 되면 아래를 실행
firewall-cmd --reload # permanent 설정 즉시 반영
오늘 원격 Docker 실습 흐름 정리
① docker.service에 -H tcp://0.0.0.0:2375 추가 (rocky = Server 개방)
② firewall 2375 열기 + --reload (길 뚫기)
③ ubuntu(Client) → rocky(Server) 원격 접속 (docker -H <IP>:2375)
④ nginx 컨테이너 실행 성공 ✅
에러를 통해 배운 것
| no such host | 이름/placeholder 문제 | 목적지는 유효한 IP여야 |
| no route to host | 방화벽/reload 누락 | permanent는 reload로 즉시 반영 |

3-7. Docker 기본 명령어

Docker Container 접속
컨테이너 안으로 들어가서 직접 작업하는 방법이다. 핵심은 -it 옵션과, 나올 때 컨테이너를 죽이지 않고 빠져나오는 escape key다.
docker run -it <이미지> <실행 app>
| -i | interactive — 입력을 계속 받음 (표준 입력 유지) |
| -t | tty — 터미널 화면 붙여줌 |
| -it | 둘을 합쳐 "터미널로 들어가 대화형 작업" |
docker run -it --name hello-world ubuntu
→ root@a5938e0c7058:/# ← 컨테이너 내부 shell로 진입!
→ 프롬프트가 root@<컨테이너ID>로 바뀐 게 안으로 들어왔다는 증거다.
나올 때 escape key
^P → ^Q (Ctrl+P 누르고, 이어서 Ctrl+Q)
| Ctrl+P → Ctrl+Q | 컨테이너 계속 실행, 접속만 해제 ✅ |
| exit 또는 Ctrl+D | 컨테이너 종료됨 (PID 1인 bash가 죽으니까) ❌ |

Docker 컨테이너 파일 수정 실습
컨테이너 안 nginx 웹페이지를 수정하고 curl로 확인
1. docker exec -it 3023 /bin/bash # 컨테이너 접속
2. cd /var/www/html # nginx 웹 폴더로 이동 (핵심)
3. echo "This is chaewon's home page" > index.nginx-debian.html # 수정
4. cat index.nginx-debian.html # 내용 확인
5. exit # 컨테이너 밖으로
6. curl 172.17.0.3 # 결과 확인 → 수정 내용 출력
| 수정이 안 됨 | 파일을 루트(/)에서 고침 | /var/www/html에서 고쳐야 함 |
| No such file | 웹 폴더엔 파일이 없었음 | echo로 새로 생성 |
| curl command not found | 컨테이너에 curl 미설치 | 호스트에서 curl 하거나 설치 |
웹서버는 지정된 폴더(/var/www/html)의 파일만 읽는다
→ 위치 틀리면 아무리 고쳐도 반영 안 됨

4. Dockerfile 작성

docker run -d -p 81:80 --name web test:nginx
docker ps # Up + 0.0.0.0:81->80 확인
curl localhost:81 # 접속

'{Bootcamp} > KT Cloud Tech up 클라우드 인프라' 카테고리의 다른 글
| [kt cloud] 도커 실습 (3) (0) | 2026.09.17 |
|---|---|
| [kt cloud] 도커 실습 (2) (0) | 2026.09.16 |
| [kt cloud] 리눅스 관리자 실습 (6) (0) | 2026.09.11 |
| [kt cloud] 리눅스 관리자 실습 (5) (0) | 2026.09.10 |
| [KT Cloud] 리눅스 관리자 실습 (4) (0) | 2026.09.09 |