Thank you for reading this post, don't forget to subscribe!
Запуск Docker в LXC
Иногда требуется запустить docker в lxc, например, для установки Docker Swarm на локальную машину, или для установки Kubernetos.
LXC позволяет запускать Docker внутри контейнера.
Рекомендуется использовать хост машину Ubuntu 18.04 и LXC контейнер с версией Centos 7.
Прежде чем начать, установите LXC на Ubuntu по инструкции.
Для того, чтобы запустить Docker в LXC нужно выполнить следующие действия:
- запустить контейнер в privileged mode
- включить мод lxc nested containers
Запуск контейнера в privileged mode
Privileged mode — это привелигированный режим, запуск контейнера от рута.
Перед установкой контейнера, нужно закоментировать строки в файле /etc/lxc/default.conf
1 2 |
#lxc.idmap = u 0 100000 65536 #lxc.idmap = g 0 100000 65536 |
Это позволит установить контейнер под рутом.
Выполните команду установки контейнера:
1 |
lxc-create -t download -n docker0 -- --dist centos --release 7 --arch amd64 |
Затем нужно обязательно раскоментировать эти строки обратно. Комментировать строки, нужно только при установке контейнера, который вы хотите, чтобы он работал в привелигированном режиме.
LXC nested containers
Nested контейнер — это возможность запустить контейнер в контейнере (вложенные контейнеры). Чтобы включить данную опцию, нужно внести изменения в конфиг LXC контейнера.
Опция включается в файле конфига контейнера /var/lib/lxc/<название контейнера>/config
Раскоментируйте строчку:
1 |
#lxc.include = /usr/share/lxc/config/nesting.conf |
Также вам понадобится прописать параметры для монтирования файловой системы cgroup и отключения AppArmor в контейнере
1 2 3 |
lxc.mount.auto = cgroup-full:rw lxc.apparmor.profile = unconfined lxc.cgroup.devices.allow = a |
Пропишите параметры сети:
1 2 |
lxc.net.0.ipv4.address = 10.0.3.20/24 lxc.net.0.ipv4.gateway = 10.0.3.1 |
А также в файле /var/lib/lxc/docker0/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0 укажите:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
DEVICE=eth0 ONBOOT=yes IPADDR=10.0.3.20 NETMASK=255.255.255.0 GATEWAY=10.0.3.1 DNS1=10.0.3.1 #BOOTPROTO=dhcp HOSTNAME=test-centos NM_CONTROLLED=no TYPE=Ethernet MTU= DHCP_HOSTNAME=`hostname` |
Установка Docker
Запустите контейнер и войдите в него:
1 2 |
lxc-start docker0 lxc-attach docker0 |
Установите docker и включите автозапуск:
1 2 3 4 5 6 |
yum install -y yum-utils yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo yum install -y docker-ce docker-ce-cli containerd.io systemctl enable docker systemctl start docker |
После установки, скачайте тестовый контейнер и убедитесь что он работает:
1 2 |
docker pull alpine docker run -it -d --name test alpine /bin/sh |
Выполните команду docker ps, должно вам выдать:
1 2 3 |
root@docker0:/# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 93f0d96197e0 alpine "/bin/sh" 28 seconds ago Up 25 seconds test |
Проверьте работу контейнера:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
root@docker0:/# docker exec -it test ping google.com PING google.com (64.233.164.101): 56 data bytes 64 bytes from 64.233.164.101: seq=0 ttl=42 time=222.140 ms 64 bytes from 64.233.164.101: seq=1 ttl=42 time=140.911 ms ^C --- google.com ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 140.911/181.525/222.140 ms root@docker0:/# docker exec -it test ifconfig eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 inet addr:172.17.0.2 Bcast:172.17.255.255 Mask:255.255.0.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:34 errors:0 dropped:0 overruns:0 frame:0 TX packets:33 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:3728 (3.6 KiB) TX bytes:3293 (3.2 KiB) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) |
Возникаемые ошибки
Если возникают ошибки:
1 2 3 |
docker: Error response from daemon: Could not check if docker-default AppArmor profile was loaded: open /sys/kernel/security/apparmor/profiles: permission denied. |
1 2 |
failed to register layer: Error processing tar file(exit status 1): remount /, flags: 0x84000: permission denied |
1 2 3 4 5 6 7 |
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "process_linux.go:430: container init caused \"process_linux.go:396: setting cgroup config for procHooks process caused \\\" failed to write c 10:200 rwm to devices.allow: write /sys/fs/cgroup/devices/docker/27822e65d0ccd42267cd420309f1de3ea2ddfc353d18d9ab9d362b0549b43ed0/devices.allow: operation not permitted\\\"\"": unknown. |
То это скорее всего связано с AppArmor. Сделайте tail -n 20 /var/log/syslog. Если в логе присутсвуют следующие строки:
1 2 3 4 5 |
Jul 16 23:49:04 alfabook kernel: [45843.968279] audit: type=1400 audit(1563299344.593:66): apparmor="DENIED" operation="mount" info="failed flags match" error=-13 profile="lxc-container-default-cgns" name="/" pid=5274 comm="exe" flags="rw, rslave" |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Jul 17 00:00:05 alfabook kernel: [46504.633713] audit: type=1400 audit(1563300005.284:68): apparmor="DENIED" operation="mount" info="failed flags match" error=-13 profile="lxc-container-default-with-nesting" name="/run/docker/runtime-runc/moby/0f36b9a62ec3234ad83b341a67f1a2f16c5db3dc55a6827720b85e30f0ecc547/runc.DcCoEi" pid=7011 comm="exe" flags="ro, remount, bind" Jul 17 00:00:05 alfabook kernel: [46504.676276] audit: type=1400 audit(1563300005.328:69): apparmor="DENIED" operation="mount" info="failed flags match" error=-13 profile="lxc-container-default-with-nesting" name="/var/lib/docker/overlay2/f40a7cc6f04db2b5cd48ddf8ec82303e07d9a744241250852c4462c12aa58df1/merged/" pid=7028 comm="runc:[2:INIT]" srcname="/var/lib/docker/overlay2/f40a7cc6f04db2b5cd48ddf8ec82303e07d9a744241250852c4462c12aa58df1/merged/" flags="rw, rbind" |
То, да причина в AppArmor. Обычно в конфиг LXC lxc.apparmor.profile, lxc.mount.auto, lxc.cgroup.devices.allow помогает. Но если не помогло, то выполните следующие команды:
Включите обучение AppArmor
1 |
aa-complain /etc/apparmor.d/* |
Запустите LXC контейнеры, и попробуйте заново запустить docker. Затем, после выдачи ошибки, перейдите на хост машину и выполните команду aa-logprof. Данная комманда анализирует лог /var/log/syslog и предлагает вам варианты патчинга правил AppArmor.
Пропатчите конфиг AppArmor и затем выключите обучение:
1 |
aa-enforce /etc/apparmor.d/* |