13년차의 서버실

서버, 인프라, 홈랩 기술 블로그

[태그:] nesting

  • Proxmox LXC 안에서 Docker 돌리기 — nesting·keyctl과 함정들

    Proxmox에서 어떤 서비스를 올릴 때, 무거운 VM을 통째로 띄우는 대신 가벼운 LXC 컨테이너 안에서 Docker를 돌리는 방법이 있습니다. 저는 사진 서버(Immich)도, 이 블로그 자동화 봇도 이 방식으로 운영합니다. 실제 설정과 반드시 알아야 할 함정을 정리합니다.

    1. 왜 VM이 아니라 LXC + Docker인가

    • 가볍다: LXC는 호스트 커널을 공유해서 VM보다 메모리·오버헤드가 훨씬 적습니다.
    • 빠르다: 부팅이 거의 즉시고, 자원 낭비가 적습니다.
    • Docker 생태계 그대로: compose 파일과 이미지를 그대로 씁니다.

    단, “다른 커널이 필요하다”거나 “강한 격리가 필수”라면 그땐 VM이 맞습니다. 일반적인 웹서비스·봇·셀프호스팅 앱이라면 LXC + Docker가 가성비 최고입니다.

    2. 핵심 — 두 개의 기능 플래그

    기본 LXC에 Docker를 깔면 안 돌아갑니다. 두 가지 features를 켜야 합니다.

    # 컨테이너(예: 113)에 nesting + keyctl 활성화
    pct set 113 --features nesting=1,keyctl=1
    플래그 역할
    nesting=1 컨테이너 안에서 또 컨테이너(Docker) 실행 허용
    keyctl=1 Docker가 쓰는 커널 키링 접근 허용

    실제로 제 컨테이너들은 이렇게 잡혀 있습니다 — 봇 컨테이너는 nesting=1,keyctl=1, Immich 컨테이너는 nesting=1. 그리고 둘 다 unprivileged(비특권) 컨테이너입니다. 보안상 가능하면 unprivileged로 두는 걸 권합니다.

    3. Docker 설치

    플래그를 켜고 컨테이너를 재시작한 뒤, 안에서 평범하게 Docker를 설치하면 됩니다.

    # LXC 내부에서 (공식 스크립트)
    curl -fsSL https://get.docker.com | sh
    docker --version   # 예: Docker version 29.4.0
    docker compose version

    4. 반드시 밟는 함정 — 좀비 프로세스

    여기서 많은 분이 당합니다. 컨테이너 안에서 자식 프로세스를 반복 생성하는 앱(브라우저 자동화, 이미지 변환 등)을 Docker로 돌리면, 죽은 자식이 좀비로 쌓입니다. 컨테이너의 PID 1이 이를 거두지 않기 때문입니다(저는 이걸로 좀비 307개를 만든 적이 있습니다 — 관련 글).

    # docker-compose.yml — tini를 PID 1로 넣어 좀비 자동 수거
    services:
      app:
        image: my-app:latest
        init: true

    5. 그 외 실전 주의점

    • rootfs 용량: Docker 이미지·빌드 캐시가 금방 쌓입니다. LXC rootfs를 넉넉히(무거운 이미지는 16GB+) 잡고, docker builder prune을 주기적으로.
    • 데이터는 볼륨으로: 컨테이너를 갈아엎어도 데이터가 남게, 영구 데이터는 호스트 경로/NAS 볼륨에 마운트.
    • 백업: LXC 자체를 Proxmox 스냅샷/백업하면 Docker 스택까지 통째로 보존됩니다.

    6. 정리

    LXC + Docker는 홈랩에서 VM의 무게 없이 Docker 생태계를 쓰는 최적의 절충안입니다. 핵심은 딱 두 가지 — nesting=1과 keyctl=1을 켜는 것, 그리고 서브프로세스 앱엔 init: true를 잊지 않는 것. 이 두 개만 챙기면 미니 PC 한 대에 서비스를 훨씬 많이 얹을 수 있습니다.