Running docker

Hi all,

I’m trying to get Docker installed, and have been having some success, but am now stuck at the point of getting the daemon to run.

The install was straightforward and mostly follows the official instructions for armhf, the only adjustment was to replace /etc/apt/sources.list with this one, which applies the universe/restricted/multiverse before running sudo apt-get update.

With that done, it downloads and installs, however systemctl cannot start the daemon. The error is:

Mar 06 14:24:43 snoodle-29 dockerd[9355]: time="2019-03-06T14:24:43.199374320Z" level=info msg="Graph migration to content-addressability took 0.00 seconds" Mar 06 14:24:43 snoodle-29 dockerd[9355]: time="2019-03-06T14:24:43.201050225Z" level=warning msg="Your kernel does not support cgroup memory limit" Mar 06 14:24:43 snoodle-29 dockerd[9355]: time="2019-03-06T14:24:43.201284652Z" level=warning msg="Unable to find cpu cgroup in mounts" Mar 06 14:24:43 snoodle-29 dockerd[9355]: time="2019-03-06T14:24:43.201809667Z" level=warning msg="Unable to find blkio cgroup in mounts" Mar 06 14:24:43 snoodle-29 dockerd[9355]: time="2019-03-06T14:24:43.202066858Z" level=warning msg="Unable to find cpuset cgroup in mounts" Mar 06 14:24:43 snoodle-29 dockerd[9355]: time="2019-03-06T14:24:43.202558567Z" level=warning msg="mountpoint for pids not found" Mar 06 14:24:43 snoodle-29 dockerd[9355]: Error starting daemon: Devices cgroup isn't mounted Mar 06 14:24:43 snoodle-29 systemd[1]: docker.service: Main process exited, code=exited, status=1/FAILURE Mar 06 14:24:43 snoodle-29 systemd[1]: Failed to start Docker Application Container Engine. -- Subject: Unit docker.service has failed
There are plenty of other people with this error. However, I've been unable to find a solution.

This looks like an issue with cgroups. Docker has a page on cgroups.

It looks like cgroups is being mounted:

snickerdoodle@snoodle-29:~$ grep cgroup /proc/mounts tmpfs /sys/fs/cgroup tmpfs rw,mode=755 0 0 cgroup /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd 0 0
Which means that some of the help ("install cgroups-lite" or "install cgroups-mount" and then manually start docker) doesn't work.

Further in the Docker cgroups page it looks like the first warning “Your kernel does not support cgroup memory limit” can be fixed by adding “cgroup_enable=memory swapaccount=1” to the “kernel command line parameters”. Again, online help points to editing this in the grub file, but that seems to be missing.

This leads to issue 1: Where does one specify the “kernel command line parameters”?

Now the other warning “Unable to find <cpu, blkio, cpuset, pids> cgroup in mounts”. This looks like maybe those are not set in the kernel… and then ultimately lead to the “Devices cgroup isn’t mounted” error? Here I’m out of my league. The one useful answer I found suggests rebuilding the kernel. I don’t have this capability, but if someone could test that, I would be appreciative.

Success!

Nick provided me with instructions for how to build the kernel.

First, find the missing kernel modules by running this helper script from docker:

wget https://raw.githubusercontent.com/docker/docker/master/contrib/check-config.sh chmod +x check-config.sh ./check-config.sh
The first section under "Generally Necessary:" lists the required modules. Now that we know what need to be turned on, let's build the kernel. Get the build dependencies:
sudo apt-get install libncurses5-dev libncursesw5-dev sudo apt-get install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi libncurses5-dev sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf sudo apt-get install u-boot-tools lzop
Then get your kernel code:
git clone <your kernel here>
Now run the configuration tool:
make ARCH=arm menuconfig
This tool looks imposing, but is quite simple to use once you know the tricks. Go through each missing kernel module and enable it. For example, I'll use "CONFIG_IP_NF_NAT". Pull up the search feature by typing "/" and enter just the key; "IP_NF_NAT". You'll get a search return that looks like:
│ Symbol: IP_NF_NAT [=n] │ Type : tristate │ Prompt: iptables NAT support │ Location: │ -> Networking support (NET [=y]) │ -> Networking options │ -> Network packet filtering framework (Netfilter) (NETFILTER [=y]) │ -> IP: Netfilter Configuration │ (1) -> IP tables support (required for filtering/masq/NAT) (IP_NF_IPTABLES [=y]) │ Defined at net/ipv4/netfilter/Kconfig:270 │ Depends on: NET [=y] && INET [=y] && NETFILTER [=y] && IP_NF_IPTABLES [=y] && NF_CONNTRACK_IPV4 [=n] │ Selects: NF_NAT [=n] && NF_NAT_IPV4 [=n] && NETFILTER_XT_NAT [=n]
The first line "Symbol: IP_NF_NAT [=n] " tells you that it is not enabled (okay, we knew this going in). The second line ("Type : tristate") tells us that it has three options; enabled ('y') disabled ('n') and enabled as a module ('m'). The third line "Prompt: iptables NAT support" tells us what it's called in menuconfig (ie; look for this string, not "IP_NF_NAT"). The " Location:" tree tells us how to navigate through menuconfig to find and enable this option.

Don’t get excited though, because it probably won’t actually appear there. Why? Skip ahead to the “Depends on:” line. If any of those say “[=n]” this key is hidden. So, in this case, “NF_CONNTRACK_IPV4 [=n]” needs to be enabled first. Start the search over for each of these dependencies until they all say “[=y]”.

If all of the dependencies are “[=y]” then we can enable this module. Again, use the “Location:” tree to navigate menuconfig, (select “Networking support” then “Networking options”, etc. etc.), and remember to look for the text next to “Prompt:”, in this case; “iptables NAT support” instead of “IP_NF_NAT”. When you find that you can type “y” for build it into the kernel or “m” for module (because this is a tristate variable, boolean variables can be either ‘y’ or ‘n’).

Repeat the super recursive process (search, check check dependencies, enable) until you have all of the required kernel modules enabled. For extra fun, enable the “Optional Features”.

Finally, build the kernel and modules (<N> = number of available threads and can be found through nsproc or lscpu):

make -j<N> ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- LOADADDR=0x8000 uImage sudo make -j<N> ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
Mount your SD card and copy the kernel and modules over:
cp arch/arm/boot/uImage /<mountpoint>/BOOT/ sudo make -j<N> ARCH=arm INSTALL_MOD_PATH=/<mountpoint>/ROOTFS/ modules_install
And you should be good to go!

keclayor, this is awesome! Nice work. How would you feel about re-posting this to our Hackster projects page?? If you’re open to it, I’ll get it featured on the website.

-Ryan