rootless Docker — br_netfilter 로드 실패

기초·개념3분조회

컨테이너를 만들고 지우는 매니저 프로세스가 하나 돌고 있는데, 이 프로세스를 root 로 띄울 수 없는 상황이었습니다. 그렇다고 root 로 뜬 Docker 데몬에 붙이면 컨테이너 레이어에 파일을 쓸 때 권한이 어긋나서, 데몬을 아예 매니저와 같은 사용자로 띄우는 rootless 모드로 갔습니다.

그런데 데몬이 시작하다 죽었습니다.

br_netfilter 로드 실패로 데몬 종료

로그 끝에 이렇게 나왔습니다.

Running modprobe bridge br_netfilter failed with message:
modprobe: ERROR: could not insert 'br_netfilter': Operation not permitted

failed to start daemon: Error initializing network controller:
error creating default "bridge" network:
cannot restrict inter-container communication:
ensure that the br_netfilter kernel module is loaded

br_netfilter 는 커널 모듈입니다. 모듈을 올리는 modprobe 는 커널을 건드리는 작업이라 root 가 필요합니다. rootless 데몬은 root 가 아니니 Operation not permitted 가 납니다.

rootless는 bridge 미사용, 기본 설정은 bridge 요구

그런데 여기서 전제가 깨지는데, rootless Docker 는 컨테이너 네트워크로 bridge 가 아니라 slirp4netns 를 써서 애초에 bridge 네트워크를 안 만듭니다.

그런데 데몬이 시작할 때 기본 bridge 네트워크(docker0)를 구성하려 하고, 그 과정에서 br_netfilter 를 요구합니다. 안 쓸 네트워크를 준비하려다 못 올리는 모듈에 막혀서 데몬 전체가 안 뜨는 겁니다.

~/.config/docker/daemon.json 에서 bridge 관련 기능을 끕니다.

{
  "iptables": false,
  "ip6tables": false,
  "bridge": "none"
}

rootless 는 어차피 이 기능들을 안 쓰니 꺼도 잃는 게 없습니다. 데몬이 bridge 구성 단계를 건너뛰고 정상적으로 뜹니다.

사전 준비 사항

rootless 데몬을 세팅하기 전에 걸리는 것들입니다.

storage driver 는 overlay2 여야 합니다. AUFS 는 rootless 데몬을 지원하지 않습니다.

필요한 패키지가 따로 있습니다.

apt-get install -y dbus-user-session docker-ce-rootless-extras uidmap

사용자 세션이 로그인 없이도 유지돼야 합니다. 데몬을 user systemd 서비스로 띄우는데, 그 사용자가 로그인 상태가 아니면 서비스가 안 붙습니다.

loginctl enable-linger <username>

이걸 안 하면 systemctl --userFailed to connect to bus: No such file or directory 로 실패합니다. machinectl shell <username>@ 로 붙어서 작업하면 세션이 잡힙니다.

rootless를 택한 이유

컨테이너 레이어에 파일을 직접 써넣는 구조라면 그 write 권한이 root 에게 있습니다. 컨테이너 레이어를 만드는 게 Docker 데몬이고, 데몬이 root 로 떠 있기 때문입니다.

매니저 프로세스가 docker cp 같은 방식으로 우회하도록 앱 로직을 고치는 방법도 있지만, 사이드 이펙트 검증이 필요하고 공수가 큽니다. 그래서 앱을 안 고치고, 데몬을 매니저 프로세스와 같은 사용자로 띄우는 쪽을 택했습니다. 데몬과 매니저가 같은 사용자면 권한 문제가 사라집니다.

  1. 불러오는 중