Docker system prune – not always what you expect

Containers have improved my ‘home lab’ significantly. I’ve run a server at home (exposed to the internet) for many years. Linux has made this both easy to do, and fairly secure.

However, in the old – “I’ll just install these packages on my linux box” – model, you’d end up with package A needing some dependency and package B needing the same one, then you’d have version conflicts. It was always something you could resolve, but with enough software you’d have a mess of dependencies to figure out.

Containers solves this by giving you a lightweight ‘virtualization’ isolating each of your packages from each other AND it also is a very convenient distribution mechanism. This allows you to easily get a complete functional application with all of it’s dependencies in a single bundle. I’ll point at linuxserver.io as a great place to get curated images from. Also, consider having an update policy to help you keep current, something like DUIN, or fully automate with watchtower.

Watchtower does have the ability to do some cleanup for you, but I’m not using watchtower (yet). I have included some image clean up into my makefiles because I was trying to fight filesystem bloat due to updates. While I don’t want to prematurely delete anything, I also don’t want a lot of old cruft using up my disk space.

I recently became aware of the large number of docker volumes on my system. I didn’t count, but it was well over 50 (the list filled my terminal window). This seemed odd, some of them had a creation date of 2019.

Let’s just remove them docker volume prune – yup, remove all volumes not used by at least one container. Hmm, no – I still have so many. Let’s investigate further.

What? If I sub in a volume id that I know is attached to a container, I do get the container shown to me. This feels like both docker system prune and docker volume prune are broken.

Thankfully the internet is helpful if you know what to search for. Stackoverflow helped me out. It in turn pointed me at a github issue. Here is what I understand from those.

Docker has both anonymous and named volumes. Unfortunately, many people were naming volumes and treating them like permanent objects. Running docker system prune was removing these named volumes if there wasn’t a container associated with it. Losing data sucks, so docker has changed to not remove named volumes as part of a prune operation.

In my case, I had some container images which had mount points that I wasn’t specifying as part of my setup. An example is a /var/log mount – so when I create the container, docker is creating a volume on my behalf – and it’s a named volume. When I recreate that image, I’m getting a new volume and ‘leaking’ a named volume which is no longer attached to a container. This explains why I had 50+ volumes hanging out.

You can easily fix this

Yup, now I have very few docker volumes on my system – the remaining ones are associated with either a running or a stopped container.

Pixel 1 data recovery.. (backup your data)

Like many parents, my kids have hand me down phones. This is generally a great way to extend the life of a device, and teenagers can be tough on phones. Some more than others.

My oldest has been one of those kids who has been generally gentle with technology, and the devices tend to last. I’ve replaced a few tempered glass screen protectors but those are disposable. I have to admit that I didn’t take the signs of problems seriously when the screen on the Google Pixel 1 started to go black occasionally – a hard reboot often fixed things up. This was just some mysterious software issue I thought.

Nope. It was the early signs of the screen going bad. One day, the screen just stayed black no matter what I did. Did we have a recent backup? Nope, it was many months old. That’s also on me. At the first sign of any weirdness with a mobile device, checking the current backup status should be a high priority.

This device was running LineageOS, and unfortunately the default security is pretty good. Oh, I tried lots of things. Blindly, boot device into fastboot mode. Load a recovery via fastboot – connect to that via adb.. but just not enough magic to get through decrypting the filesystem via recovery without access to the screen. This was back in 2020. I would try from time to time to figure out a way to recover a screen-less Android phone running LineageOS, but it continued to resist my attempts.

The picture at the top of the post is the very busted screen from the Pixel 1. At one point in my recovery attempts I thought – maybe it’s simply that the ribbon cable needs to be re-seated? Despite being careful, I can safely report that removing the screen is very hard and you’re likely to break it. I pretty much destroyed that screen.

I had reached out to a local repair shop, but they only were interested in selling me a complete screen replacement – not helping me hook up a screen and recover the data. I continued to look for economical screen replacement options, but at this point I didn’t even know if the screen was the problem.

Just the other day, I found a pair of used Pixel1 screens for $30 + $10 shipping. This was cheap enough that it was worth the risk. I got lucky, the used screen was exactly what I needed.

Cool. There is hope. The phone battery was very dead, so it wasn’t allowing me to power it on. My initial attempts to power on were also scary, I kept getting “no OS found, corrupted data”. I was able to boot to the fastboot screen, but not able to start the recovery image (if there even is one?).

After a few minutes of charging, and more attempts to boot – it started to load!

I was so happy to see the LineageOS boot screen. Now I was crossing my fingers hoping I’d get a full boot without problems. This next image increased my joy.

The touch screen worked fine, and I was able to log in. I was so close to being able to recover the files from this phone, but I had to let it charge up.

Once it was charged, unlocking the phone and connecting a laptop to it was trivial. I was able to pull down the 900+ photos and push them up to my fileserver for safe keeping. In the end it took a couple of years to recover, but I’m glad I kept at it. I also was very lucky that it was only the screen.

Go backup your data. Better yet, invest the time to create a regular backup system. Test your backups.

Running Selenium testing in a single Docker container

Selenium is a pretty neat bit of kit, it is a framework that makes it easy to create browser automation for testing and other web-scraping activities. Unfortunately it seems there is a dependency mess just to get going, and when I hit these types of problems I turn to Docker to contain the mess.

While there are a number of “Selenium + Docker” posts out there, many have more complex multi-container setups. I wanted a very simple single container to have Chrome + Selenium + my code to go grab something off the web. This article is close, but doesn’t work out of the box due to various software updates. This blog post will cover the changes needed.

First up is the Dockerfile.

The changes needed from the original article are minor. Since Chrome 115 the chromedriver has changed locations, and the zip file layout is slightly different. I also updated it to pull the latest version of Selenium.

ChromeDriver is a standalone server that implements the W3C WebDriver standard. This is what Selenium will use to control the Chrome browser.

The second part is the Python script tests.py

Again, only minor changes here to account for changes in Selenium APIs. This script does do some of the key ‘tricks’ to ensure that Chrome will run inside Docker (providing a few arguments to Chrome).

This is a very basic ‘hello world’ style test case, but it’s a starting point to start writing a more complicated web scraper.

Building is as simple as:

And then we run it and get output on stdout:

Armed with this simple Docker container, and using the Python Selenium documentation you can now scrape complex web pages with relative ease.