undocker, run a Docker image without Docker
I self-host on *.benpro.fr a lot of things with LXD, right now I have 20 LXC containers managed by LXD on a single machine.
When I want to self-host something, there are three possibilities:
- The software is packaged in Debian/Ubuntu or Archlinux: I just launch a new container, and install the software with the package manager. For example, this is the case of Miniflux.
- The software is not packaged but there is a production install guide: I just launch a new container and do all the necessary actions. For example, this is the case of Mastodon.
- The software is only available via Docker: I could try to translate the Dockerfile to manual steps but I prefer to just not use it.
But thanks to a new discovery, this has changed!
I discovered undocker and skopeo. With these two tools you can easily extract a Docker image (a succession of “layers”), and run the app out of Docker.
I tried with Photoview. Here is the basic guideline:
- Deploy with LXD a LXC container with the same Linux distribution as the Dockerfile use.
- Install MariaDB since the app need a database.
- Extract the Docker image.
- Identify required environment variable by reading the Dockerfile and Docker compose.
- Create a systemd unit file.
- Launch the application with systemd.
- ???
- Profit! Give the middle finger to Docker!
Here are the steps for Photoview:
$ lxc launch images:debian/11 gallery
$ lxc exec gallery bash
# apt install mariadb-server skopeo wget
# mysql -e "CREATE DATABASE photoview; GRANT ALL PRIVILEGES ON photoview.* TO 'photoview'@localhost IDENTIFIED BY '<PASSOWRD>'"
# wget https://git.sr.ht/~motiejus/undocker/refs/download/v1.0.1/undocker-linux-amd64-v1.0.1 -O /tmp/undocker
# install -m 755 /tmp/undocker /usr/local/bin/undocker
# adduser --disabled-password photoview
# sudo -iu photoview
$ skopeo copy docker://docker.io/viktorstrate/photoview:latest docker-archive:photoview.tar
$ mkdir photoview cache
$ cd photoview
$ undocker ~/photoview.tar - | tar -xv
$ cat << EOT > ~/.env
PHOTOVIEW_LISTEN_IP=127.0.1.1
PHOTOVIEW_LISTEN_PORT=1234
PHOTOVIEW_SERVE_UI=1
PHOTOVIEW_UI_PATH=/ui
PHOTOVIEW_DATABASE_DRIVER=mysql
PHOTOVIEW_MYSQL_URL='photoview:<PASSWORD>@tcp(127.0.0.1)/photoview'
PHOTOVIEW_MEDIA_CACHE=/home/photoview/cache
MAPBOX_TOKEN=<TOKEN>
EOT
# cat << EOT > /etc/systemd/system/photoview.service
[Unit]
Description=Photoview
After=network.target
Requires=mariadb.service
[Service]
Type=simple
User=photoview
EnvironmentFile=/home/photoview/.env
BindReadOnlyPaths=/proc
WorkingDirectory=/app
RootDirectory=/home/photoview/photoview
ExecStart=/app/photoview
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOT
# systemctl daemon-reload
# systemctl enable --now photoview
# systemctl status photoview
● photoview.service - Photoview
Loaded: loaded (/etc/systemd/system/photoview.service; enabled; vendor preset: enabled)
Drop-In: /run/systemd/system/service.d
└─zzz-lxc-service.conf
Active: active (running) since Sun 2021-09-05 12:49:47 UTC; 8s ago
Main PID: 4643 (photoview)
Tasks: 9 (limit: 7084)
Memory: 54.1M
CGroup: /system.slice/photoview.service
├─4643 /app/photoview
└─4653 /usr/bin/perl -w /usr/bin/exiftool -stay_open True -@ - -common_args -n
Sep 05 12:49:47 test photoview[4643]: 2021/09/05 12:49:47 Scan interval runner: Waiting for signal
Sep 05 12:49:47 test photoview[4643]: 2021/09/05 12:49:47 Scan interval runner: New ticker detected
Sep 05 12:49:47 test photoview[4643]: 2021/09/05 12:49:47 Scan interval runner: Waiting for signal
Sep 05 12:49:47 test photoview[4643]: 2021/09/05 12:49:47 Found executable worker: darktable (this is darktable-cli>
Sep 05 12:49:47 test photoview[4643]: 2021/09/05 12:49:47 Found executable worker: ffmpeg (ffmpeg version 4.3.2-0+d>
Sep 05 12:49:47 test photoview[4643]: 2021/09/05 12:49:47 Found exiftool
Sep 05 12:49:47 test photoview[4643]: 2021/09/05 12:49:47 Initializing face detector
Sep 05 12:49:48 test photoview[4643]: 2021/09/05 12:49:48 Photoview API endpoint listening at http://127.0.1.1:1234>
Sep 05 12:49:48 test photoview[4643]: 2021/09/05 12:49:48 Photoview API public endpoint ready at /api
Sep 05 12:49:48 test photoview[4643]: 2021/09/05 12:49:48 Photoview UI public endpoint ready at /
And voilà! 🎉
Now, you still have the the same issue as using Docker, the Dockerfile may have used old software and libraries when compiling the application... But, somehow I find it better, and it integrate well with my LXD usage.
Note that it is also possible to not use RootDirectory
in the systemd unit file and install all the required dependencies (ffmpeg, darktable, ...) and it may also work, having more control on these dependencies, instead of relying of what is shipped in the Docker image.