Super Kawaii Cute Cat Kaoani
본문 바로가기
{Bootcamp}/KT Cloud Tech up 클라우드 인프라

[kt cloud] 도커 실습 (1)

by wonee1 2026. 9. 15.
728x90

 

 

 

 

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

전가상화, 다양한 os 설치 가능

2) 반가상화 (Para-Virtualization)


전가상화처럼 하이퍼바이저가 공유 자원을 중재하지만, 제어 코드를 Guest OS에 심어줘야 한다는 제약이 있는 방식이다.

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

 

 

반가상화

 

 

kvm type 2 모습 => kvm 유료는 type 1 무료는 type 2

 

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. 클라우드 컴퓨팅 

 

IaaS 예시 => ec2

 

 

 

 

 

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로 즉시 반영

 

 

 

alias 설정 해놓기

 

 

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                # 접속

 

 

 

 

 

 

 

728x90