Converting docker containers into AppImages
Posted on Sat 03 September 2022 in Linux, packaging, AppImage, Docker
In Linux, software is conventionally distributed through packages, usually compressed folders including executables, installations scripts and various configuration files. These packaging formats come in various flavors like deb packages, RPMs, and many others. While very useful, these packaging formats have a downside: they are distribution specific. Even if two distributions use the same packaging format, like say Ubuntu and Debian, they are not compatible. Meaning that a deb package built for debian is not expected to work on Ubuntu and vice-versa. In goes even further, packages may not be compatible between two different releases of the same Linux distribution, for instance Debian stable and Debian unstable. The main consequence of this limitation is that software needs to be built for every combintations of Linux distribution / releases out there.
For simple open source software this isn't usually a big issue, as volunteers can usually take the code and release it for the distribution of their choice making small adjustments to the code (at least in principle). For more complicated software and proprietary software this is trickier. However there is a solution to this problem: recently new universal, meaning distribution agnostic, packaging formats have been created. The main ones are Flatpak, Snaps and AppImage. But there are many others, technically Docker is also a means to distributed software (usually server-side software) on many Linux distributions (as well as Windows). Steam distributables can also be counted, if you think about it. And even Nix packages are in some way distribution agnostic as you can install Nix on many Linux distributions.
I personally think AppImage lacks a little bit of love. It does not offer as many features as Flatpak or Snaps, which handle sandboxing, software distribution, and sharing frameworks, but it is very simple and easy to grasp. AppImages is already fairly popular amongst QT applications, electron applications, and some games like OpenRA. By the way that is no coincidence, among the tools to build appimages, some are specifically tailored for QT applications and electron applications. This, in my view, creates a disparity, so I wondered if I can make a difference. So I decided to create another tool to create AppImages, but from Docker containers, a tool I am familiar with. Furthermore the creation of Docker images and containers is very well documented and the collection of publically available Docker images is very large. The tool's name docker2appimage available on Github at https://github.com/mparusinski/docker2appimage.
If you have a container called relaxed_beaver, to create an AppImage which triggers the container default command, you run.
docker2appimage relaxed_beaver
You can perform more complex tasks like request docker2appimage to create a container from the alpine Docker image and create a container that calls ls and give the AppImage the name alpine-ls
docker2appimage -x ls --name alpine-ls -i alpine
In order to work the tool requires the appimagetool AppImage to be accessible on the path as well imagemagick to be installed on the system. The entire tool is a simple shell script for it is designed to be portable.
Here is an even more complex example where we create an universal binary for ripgrep a popular alternative for grep
docker run -it --name=ripgrep ubuntu # Creates a container called neofetch
apt-get update && apt-get install -y ripgrep # Command within the container
exit # Leave the container
docker2appimage -x rg ripgrep
The last commmand creates an AppImage called neofetch from container neofetch which launches neofetch
Most Docker images are server side software (e.g. nginx), OS containers (e.g. alpine) and programming frameworks. Naturally docker2appimage will fit well to create CLI only AppImage. This is not what AppImage are usually intended, they are usually intended for Desktop applications. It is still possible to create GUI applications, and there is a case for CLI AppImages as a replacement for statically compiled binaries. In other words this offers an approach for portable CLI applications.
There are some limitations of course. Many Docker images default commands are shells like bash, sh, ... one might even include Python as a type of shell. AppImage works by doing tricks with environment variables and Fuse to create a pseudo virtual environment where a command is launched from within the AppImage. This makes handling shell commands trickier, so it is not supported, instead it is better to use the -x flag that allows the user to specify the command to launch.
The project is still ongoing development to support many applications and Linux distributions. If you have some time and are curious do not hesitate to test the tool and report any bugs you see.