기본 개념에 이어 실습하기 전 환경 구축을 하기 위한 문서입니다.
세 tier에 동일한 nginx를 올려 비교 준비를 끝내는 단계입니다.
모든 명령은 실험 서버(vm-nangman-dev-taekjun-wisoft, root)에서 실행하겠습니다.
배포 후 접근 지점(포트 충돌 방지):
| tier | 실체 | 접근 |
|---|---|---|
| VM | 이 호스트 자신에 직접 설치 | http://localhost:80 |
| Docker | nginx 컨테이너 | http://localhost:8080 (-p 8080:80) |
| LXC | nginx 시스템 컨테이너 | http://localhost:8081 (proxy device) |
echo "== 커널/가상화 =="; uname -a; systemd-detect-virt
echo "== 부팅 시간(VM tier) =="; systemd-analyze
echo "== 자원 =="; nproc; free -h; df -h /
echo "== 네트워크 =="; ip -br addr; ip route
echo "== 기존 설치 여부 =="; which docker lxc lxd incus snap 2>/dev/null; echo "---"
echo "== cgroup 버전 =="; stat -fc %T /sys/fs/cgroup # cgroup2fs 이면 v2
echo "== nginx/포트 흔적 =="; which nginx 2>/dev/null; ss -tlnp | grep -E ':80|:8080|:8081' || echo "80/8080/8081 미사용"
확인 포인트: Docker/LXD 미설치 여부, 80·8080·8081 포트가 비어 있는지, cgroup v2 인지.
docker --version && systemctl is-active docker
docker info | grep -iE 'storage driver|cgroup version' # overlay2 / v2 확인
docker ps -a # 기존 컨테이너 확인

이 서버엔 Docker 29.1.3이 이미 설치·기동 중이라 설치를 건너뛰겠습니다.
lxd init --auto # 기본 스토리지풀 + lxdbr0 브리지(NAT) 자동 구성
lxc network list # lxdbr0 생성 확인

공정성: 컨테이너 두 tier에 CPU 1 / RAM 512MiB 상한
VM tier(호스트 직접 설치)는 게스트 전체를 쓰는 것이 정상 배치이므로 상한 없이 두고, 측정 시 nginx 프로세스 자체의 풋프린트를 비교합니다.
이 단계만 관리형 서버의 base OS(ClamAV·Teleport 상주)에 서비스를 추가합니다.
컨테이너 tier와 달리 격리되지 않으므로 실행 전 확인을 받고 진행합니다.
되돌리기:
systemctl disable --now nginx && apt-get remove -y nginx
apt-get install -y nginx
systemctl enable --now nginx
curl -s -o /dev/null -w "VM nginx HTTP %{http_code}\n" http://localhost:80

docker run -d --name docker-nginx --cpus=1 -m 512m -p 8080:80 nginx:latest
sleep 2
curl -s -o /dev/null -w "Docker nginx HTTP %{http_code}\n" http://localhost:8080

사전 조치 (Docker 공존 시 필수): Docker가 iptables
FORWARD기본 정책을 DROP으로 걸어, lxdbr0에서 나가는 LXC 트래픽이 차단됩니다 (DNS는 되지만 인터넷 불가 →apt실패).Docker가 사용자 규칙용으로 비워둔
DOCKER-USER체인에 lxdbr0 통과 규칙을 먼저 넣습니다.
# [사전] Docker↔LXD FORWARD 충돌 우회: lxdbr0 포워딩 허용 (컨테이너 인터넷 접근)
iptables -I DOCKER-USER -i lxdbr0 -j ACCEPT
iptables -I DOCKER-USER -o lxdbr0 -j ACCEPT
# 되돌리기: iptables -D DOCKER-USER -i lxdbr0 -j ACCEPT; iptables -D DOCKER-USER -o lxdbr0 -j ACCEPT
# 시스템 컨테이너 생성 + 자원 상한
lxc launch ubuntu:24.04 lxc-nginx -c limits.cpu=1 -c limits.memory=512MiB
sleep 8 # 첫 launch는 이미지 다운로드로 오래 걸릴 수 있음
# 컨테이너 안에 nginx 설치
lxc exec lxc-nginx -- bash -c "apt-get update && apt-get install -y nginx && systemctl enable --now nginx"
# 호스트 8081 → 컨테이너 80 으로 프록시 노출
lxc config device add lxc-nginx web proxy listen=tcp:0.0.0.0:8081 connect=tcp:127.0.0.1:80
sleep 2
curl -s -o /dev/null -w "LXC nginx HTTP %{http_code}\n" http://localhost:8081

for t in "VM:80" "Docker:8080" "LXC:8081"; do
name=${t%%:*}; port=${t##*:}
code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:$port)
echo "$name (localhost:$port) -> HTTP $code"
done

실험 종료/재시작 때만 사용. 함부로 돌리지 말 것.
docker rm -f docker-nginx
lxc delete -f lxc-nginx
# 호스트 nginx는 VM tier 대표이므로 유지. 완전 제거 시: systemctl disable --now nginx
다음은 실제 실습을 통해 리소스 사용 및 격리 수준을 측정하는 글입니다.
감사합니다.
정택준
Team: https://nangman.cloud/ko
E-mail: taekjunnnn@nangman.cloud