Tag : linux

Docker on Debian Wheezy

Maybe you have already heard of the next revolution in application deployment called Docker. I quote:

Docker is an open-source engine which automates the deployment of applications as highly portable, self-sufficient containers which are independent of hardware, language, framework, packaging system and hosting provider.

On the getting started page, you can see that you need an Ubuntu machine to get it running:

Requirements

  • Ubuntu 12.04 (LTS) (64-bit)
  • or Ubuntu 12.10 (quantal) (64-bit)
  • The 3.8 Linux Kernel

One thing that is missing from this list, is AUFS support in the kernel, which isn’t a sure thing these days in Ubuntu.

However, I was interested in running Docker on a 64-bit Debian Wheezy machine, and this post explains how to do it. It’s not really hard, but you need to install an Ubuntu kernel. At least, I haven’t been able to find a 3.8 kernel for Wheezy just yet.

Your best bet is the 3.8 kernel from Ubuntu 13.04 Raring, backported for Ubuntu 12.04 LTS Precise. If that link is broken, try this one or get the right page from here. I have tried a kernel from Ubuntu’s mainline kernel PPA, but the 3.8 and 3.9 kernels for Raring from there seem to lack AUFS support.

I downloaded the deb named linux-image-3.8.0-23-generic_3.8.0-23.34~precise1_amd64.deb, which installs on Wheezy without problems. Just do:

$ sudo dpkg -i linux-image-3.8.0-23-generic_3.8.0-23.34~precise1_amd64.deb
$ sudo reboot

Now find a Docker package on Launchpad. Get the one that is built for Precise.

First install the dependencies:

$ sudo apt-get install lxc bsdtar

and then Docker. This will not succeed:

$ sudo dpkg -i lxc-docker_0.4.0-1_amd64.deb
Selecting previously unselected package lxc-docker.
(Reading database ... 40929 files and directories currently installed.)
Unpacking lxc-docker (from lxc-docker_0.4.0-1_amd64.deb) ...
Setting up lxc-docker (0.4.0-1) ...
/var/lib/dpkg/info/lxc-docker.postinst: 4: /var/lib/dpkg/info/lxc-docker.postinst: /sbin/start: not found
dpkg: error processing lxc-docker (--install):
 subprocess installed post-installation script returned error exit status 127
Errors were encountered while processing:
 lxc-docker

This is caused by Docker’s Ubuntu package trying to use upstart to start the daemon, which does not work on Debian. Disable that:

sed -i 's~/sbin/start~#/sbin/start~' /var/lib/dpkg/info/lxc-docker.postinst
sed -i 's~/sbin/stop~#/sbin/stop~' /var/lib/dpkg/info/lxc-docker.prerm

If you now have apt-get fix its state, it should work:

$ sudo apt-get -f install
Reading package lists... Done
Building dependency tree
Reading state information... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
1 not fully installed or removed.
After this operation, 0 B of additional disk space will be used.
Setting up lxc-docker (0.4.0-1) ...

That’s it!

Now continue with the examples on Docker’s website. Happy Docker’ing!

Rpmrebuild FTW!

A problem that I faced today, summarized in a tweet:

After some Googling, I found this blog post about a tool called rpmrebuild.

I decided to give it a go on the Oracle-supplied RPM for JDK6. It is called jdk-6u45-linux-amd64.rpm in the current directory.

$ rpmrebuild -n --change-spec-preamble='sed -e "s/^Name:.*/Name:jdk6/"' -p jdk-6u45-linux-amd64.rpm
result: /home/martijn/rpmbuild/RPMS/x86_64/jdk6-1.6.0_45-fcs.x86_64.rpm

Comparison of the original and resulting RPMs showed the following:

  • file size of the original RPM is 57MB, the result is 50MB
  • Reported Size in the output of rpm -qpi only differs 60kB
  • Name, Build Date, Build Host and Size are the only meta-information fields that changed
  • The file list of both RPMs (output of rpm -qpl) is exactly the same

This looks good, so let’s try installation:

$ sudo rpm -ivh jdk6-1.6.0_45-fcs.x86_64.rpm                                                          [0]
Preparing...                ########################################### [100%]
        file /etc/.java/.systemPrefs/.system.lock from install of jdk6-2000:1.6.0_45-fcs.x86_64 conflicts with file from package jdk-2000:1.7.0_21-fcs.x86_64
        file /etc/.java/.systemPrefs/.systemRootModFile from install of jdk6-2000:1.6.0_45-fcs.x86_64 conflicts with file from package jdk-2000:1.7.0_21-fcs.x86_64
        file /etc/init.d/jexec from install of jdk6-2000:1.6.0_45-fcs.x86_64 conflicts with file from package jdk-2000:1.7.0_21-fcs.x86_64

These file conflicts were to be expected, since the installed JDK7 also ships them. So we need more trickery, in the form of a –change-files option to rpmrebuild.

export RPMREBUILD_TMPDIR=`mktemp -d`
rpmrebuild -n \\
  --change-files="sed -i '/^%config.*\"\\/etc/d' $RPMREBUILD_TMPDIR/work/files.1" \\
  --change-spec-preamble='sed -e "s/^Name:.*/Name:jdk6/"' \\
  -p jdk-6u45-linux-amd64.rpm

$RPMREBUILD_TMPDIR/work/files.1 is the file that lists all the files to be included in the RPM. Using sed -i, we remove all the lines from that file that name a configuration file under /etc, represented by the regular expression /^%config.*\"\/etc/.

The resulting RPM seems to install nicely on a RHEL6 system that already has a Java7 SDK installed. Win! Of course, for the sake of consistency, I need to do the same thing to the Java7 RPM. Unfortunately, the Java7 RPM had one more problem, being that the postinstall scriptlet would give errors, due to the files we deleted now being missing. My final invocation for the Java7 RPM is as follows:

export RPMREBUILD_TMPDIR=`mktemp -d`
rpmrebuild -n \\
  --change-spec-preamble='sed -e "s/^Name:.*/Name:jdk7/"' \\
  --change-files="\\
    sed -i '/^%config.*\\"\\/etc/d' $RPMREBUILD_TMPDIR/work/files.1; \\
    sed -i 's/\\/etc\\/init.d\\/jexec start/#\\/etc\\/init.d\\/jexec start/' $RPMREBUILD_TMPDIR/work/post.1; \\
    sed -i 's/\\/usr\\/lib\\/lsb\\/install_initd jexec/true; #\\/usr\\/lib\\/lsb\\/install_initd jexec/' $RPMREBUILD_TMPDIR/work/post.1; \\
    sed -i 's/\\/sbin\\/chkconfig --add/true; #\\/sbin\\/chkconfig --add/' $RPMREBUILD_TMPDIR/work/post.1" \\
  -p jdk-7u21-linux-x64.rpm

Cross-compiling kernel modules for Raspbian

This is a follow-up post to my post about compiling out-of-tree kernel modules for Raspbian / Raspberry Pi from last week. In that post I talked about compiling a kernel module on the Raspberry Pi itself. This time, I did the same thing, but I did it on my i386 Ubuntu workstation, using a cross-compiler.

For this to work, you need the following software:

  • The kernel source
  • A cross-compiler, and it has to be the same version that your actual Raspbian-kernel was compiled with
  • A Module.symvers file, or the kernel and all modules built

The easiest thing is to create a directory that you keep all the Raspberry Pi stuff in. If you haven’t downloaded the kernel source yet, clone the Git repository; it allows you to stay up to date. Also download the pre-built compiler toolchain using Git:

[code]
mkdir ~/raspberrypi
cd ~/raspberrypi
git clone https://github.com/raspberrypi/linux.git
git clone https://github.com/raspberrypi/tools.git
[/code]

Just for fun & exercise, instead of using the downloaded Modules.symvers, build the kernel. See http://elinux.org/RPi_Kernel_Compilation#compiling for more detailed information.

[code]
cd linux
zcat /proc/config.gz > .config
make -j 6 ARCH=arm CROSS_COMPILE=$HOME/raspberrypi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- oldconfig
make -j 6 ARCH=arm CROSS_COMPILE=$HOME/raspberrypi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
make -j 6 ARCH=arm CROSS_COMPILE=$HOME/raspberrypi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- modules
[/code]

Please note the ‘-j 6’, which sets the number of concurrent jobs to 6, which may be less than ideal if you have a slow (single/dual core) machine. If your computer has a quad-core processor or better, -j 6 should be fine. It will make your build go a whole lot faster.

Note: if you don’t feel like waiting for a kernel build to complete, you can also use the provided Module.symvers file, prepare and configure the kernel tree and build your module from there. Please see my previous post on how to do that; just add the cross-compilation flags.

Now, you are ready to cross-compile your out-of-tree kernel module:

[code]
cd /path/to/module/source
make -C $HOME/raspberrypi/linux ARCH=arm \
CROSS_COMPILE=$HOME/raspberrypi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- \
SUBDIRS=$PWD modules
[/code]

Compiling kernel modules for Raspbian / Raspberry Pi

I needed to compile an out-of-tree (vendor supplied) driver for a USB device, to use it on my Raspberry Pi. Since the process was less than obvious, I’ll document it here. Maybe it will be of use to anyone else.

Normally, for compiling kernel modules, you need the kernel headers available. They have to match the version of the kernel you are targeting. In case of the Raspberry Pi running the 2012-07-15 image of Raspbian, that would be 3.1.9+. On plain Debian you would install a ‘linux-headers-x.y.z-flavour’ package, but that doesn’t seem to be available on Raspbian (at least not the right version), so we use the full kernel source from Github.

The main problem with that, is the absence of a file named Module.symvers, that contains the symbol versions of the running kernel and all of its modules. That file would normally come in the linux-headers package, that I mentioned above. To get that file, and be able to build ‘good’ modules for the kernel, you would need to build the entire kernel and all its modules yourself. At the end of the build, the file will be created. However, if you want to do that on the Pi itself, make sure you have plenty of time, because a complete kernel build will take quite a few hours.

To spare you the trouble, you can download it here: Module.symvers. Please note: this file is for the 3.1.9 kernel from Raspbian-2012-07-15, and it will not work for other kernel versions.

Assuming you have downloaded the file to your home directory, you can now download the Linux kernel source and prepare it for building out-of-tree modules like this:

cd /usr/src
sudo wget -O raspberrypi-linux-3.1.9.tar.gz https://github.com/raspberrypi/linux/tarball/rpi-patches
sudo tar xzf raspberrypi-linux-3.1.9.tar.gz
sudo ln -s /usr/src/raspberrypi-linux-eab45cb /lib/modules/`uname -r`/build
cd /usr/src/raspberrypi-linux-eab45cb
sudo sh -c 'zcat /proc/config.gz  > .config'
sudo sed -i 's/EXTRAVERSION =.*/EXTRAVERSION = +/' Makefile
sudo cp ~/Module.symvers .
sudo make oldconfig
sudo make modules_prepare

A few notes:

  • The name of the source directory is probably different in your case, because it contains the ID of the latest commit in the Git repository and commits occur regularly.
  • The sed command on line 7 is to add a ‘+’ to the version in the source. The version should be 3.1.9+, while the version in the repository is just 3.1.9.

Now most well-maintained drivers should ship a proper Makefile for building them, but the usual command line for building such a module would be something like this:

[code]
make -C /lib/modules/`uname -r`/build SUBDIRS=$PWD modules
[/code]

Policykit adventures

After installing Debian on a laptop this week, once again, I ran into the “problem” of not being able to shutdown or reboot the computer, when another user is logged in, for example via SSH. If you’re a Linux user, maybe you have seen it:

System policy prevents restarting the system when other users are logged in

The cause of this behaviour is something called policykit, and a policy defined in /usr/share/polkit-1/actions/org.freedesktop.consolekit.policy. I found several pages on the web, that suggested to modify this file to change the policy. However, as this file is shipped by a package, and living below /usr/share, it is not intended to be modified by users to override the policies it contains.

The correct way to fix the problem is in something called PolicyKit Local Authority, or pklocalauthority. To enable all users to shutdown or reboot the computer, even when other users are logged in, create a file named /etc/polkit-1/localauthority/50-local.d/usershutdown.pkla (the name must end in .pkla) and put the following in it:

[Allow Shutdown]
Identity=unix-user:*
Action=org.freedesktop.consolekit.system.stop-multiple-users
ResultAny=yes
ResultInactive=yes
ResultActive=yes

[Allow Restart]
Identity=unix-user:*
Action=org.freedesktop.consolekit.system.restart-multiple-users
ResultAny=yes
ResultInactive=yes
ResultActive=yes

You may have to reboot the computer (or at least log out and back in) for the policy override to take effect.