• How do you keep your Dockerfile FROM sha tags up to date?

    For my trusty followers who have been crying out for a technology-based post – TODAY IS THE DAY.

    Due to recent supply chain attacks; more platforms are going down the route of suggesting sha-pinning dependencies

    GitHub has a flag that ensures that all your GitHub Action dependencies are explicitly tied to a sha, instead of just a version tag (e.g. @v1)

    This helps to put you in control of version upgrades, as each time the author releases a new version.

    In the npm world, your package.json file defines the ‘range’ of dependencies that you ‘directly’ depend on, and the package-lock.json is a reference to all of the reified dependency tree versions that were pulled when you ‘built’ the package.

    This produced repeatable builds (when using `npm ci`), as it only ever downloaded the dependencies ‘pinned’ by the lockfile. As npm follows SemanticVersioning, when new packages are updated, the dependency tree is re-worked out, and dependabot can make suggestions for how to update your package-lock.json file to satisfy both generic updates, and security patches.

    It’s great for npm (SemVer), it’s great for GHA (SemVer), but it’s also capable of supporting Dockerfiles.

    FROM node:20-alpine

    An innocuous Dockerfile, build using the Official Node image, and follows Docker’s own documentation (from 2022).

    Way back in 2020, the first hit (for me) on Google is Bálint Biró‘s helpful blogpost on how to follow this approach for Docker images within the context of tools like docker-compose; and the official Dockerfile doc shows how to do this using the FROM argument in a dockerfile:

    FROM node:20-alpine@sha256:3bc9a4c4cc25cfde1e8f946341c85f333c36517aafda829b4bb7e785e9b5995c 

    Neat.

    However, the management of these images in DockerHub is kinda a different paradigm. The office ‘node’ image, of which 20-alpine is just a label, has quite a load of other labels:

    https://hub.docker.com/_/node

    There are tens of labels, and the label I’ve targeted is mutable. It automatically keeps me up to date whenever the official maintainers release a new version. However, it’s the same anti-pattern as the one that Github Actions recently fixed with their sha pinning.

    So, if I want to maintain 20-alpine, and I want to pin to a sha, so that I only get an update if the maintainer posts a new version of the 20-alpine label to docker hub, that’s possible right?

    Well, I tested it and put a Dockerfile the following:

    FROM node:20-alpine@sha256:3bc9a4c4cc25cfde1e8f946341c85f333c36517aafda829b4bb7e785e9b5995c

    and a dependabot.yml like so:

    # To get started with Dependabot version updates, you'll need to specify which
    # package ecosystems to update and where the package manifests are located.
    # Please see the documentation for all configuration options:
    # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
    
    version: 2
    updates:
      - package-ecosystem: "npm" # See documentation for possible values
        directory: "/" # Location of package manifests
        schedule:
          interval: "weekly"
      - package-ecosystem: "github-actions" # See documentation for possible values
        directory: "/" # Location of package manifests
        schedule:
          interval: "weekly"
      - package-ecosystem: "docker"
        directory: "/" # Location of package manifests
        schedule:
          interval: "daily"

    and to my (un-surprise, as I’d read the docs), it didn’t quite work as anticipated, with the next PR suggesting the following change:

    Bump node from 20-alpine to 25-alpine !

    Now, node’s own guidance is as follows:

    Major Node.js versions enter Current release status for six months, which gives library authors time to add support for them. After six months, odd-numbered releases (9, 11, etc.) become unsupported, and even-numbered releases (10, 12, etc.) move to Active LTS status and are ready for general use. LTS release status is “long-term support”, which typically guarantees that critical bugs will be fixed for a total of 30 months. Production applications should only use Active LTS or Maintenance LTS releases.

    So this PR is taking me from a current LTS release, in maintenace til April ’26, to a current version that’s never going to enter LTS and not recommended for production use.

    I think that it’s behaving like this because the implementation pattern that the official node maintains have taken to have loads of labels against a single image. Dependabot for docker isn’t particularly smart, and looks for a temporally later tag against the node image, rather than using the 20-alpine label to contextualise the sha and lock it against the label+sha as defined in my lovely Dockerfile.

    Now, no grief to the maintainers. The pattern that they support is a docker-hub image that uses SemVer in the label to contextualize their dependencies, so the nodeJS pattern is just one of many others that fall outside that paradigm.

    A little bit more research…

    After a quick Google, I went and found a few threads where people were cheering an alternative to dependabot for docker stuff, Renovate, by Mend.

    I’d come across this before, but being a Github native I’d always just deferred to dependabot.

    I had to install the app into my org, trust it with my test repo – but once it had been plumbed in and read my code.. It raised the PR that I wanted – a direct update of the sha for the node:20-alpine tag:

    I can see why Dependabot is struggling; but if renovate is ahead of the game here then I may be rethinking what else it’s picking up on that Dependabot is missing…

    What do you use to manage your dependencies? Is there another dependency bot that’s even better?

  • The Role of Open Source in Modern IT Solutions

    My career in IT began by developing open source solutions to provide licence-free services to small businesses. Working with a team of software enthusiasts from the north-west of the UK, I was a small cog in a wonderfully idyllic and optimistic consortium.

    My role initially consisted of travelling around small businesses in Manchester and offering a free ‘audit’ of their existing IT solutions. This was back in 2006, and around this time ‘Microsoft Small Business Server’ was what most small companies would use to host their ‘groupware’ – ultimately email, calendaring & file-sharing systems.

    As well as developing our own solution (the AZ1000!), we also offered local support for open source solutions. It was at the beginning of Web 2.0 (when you could start to right-click on the web) and we had got Zimbra! as one of the open source tools we’d support. We also had https://www.horde.org/ and a supported some Plone websites too.

    A few days ago, a little poem popped up on my LinkedIn, inspired by the “I met my #youngerself for coffee” trend. I found it quite a profound way of thinking about my wider life, but for the purposes of this post I wanted to reflect back on my tech career.

    The first thing I think my #youngerself would be disappointed with, is how little support the open source movement gets from the large corporates for whom it’s the lifeblood of their delivery. I doubt there are many projects running in the private sector that don’t make significant use of open source software, yet give very little back to the ecosystem – if they are even aware of it at all.

    Secondly, brought into stark focus by some of the more recent political changes – would be the re-coupling of IT to large American companies. In 2006, we were trying to avoid lock in to Microsoft, who had a significant monopoly on many aspects of commercial IT. We’ve just gone and done the same with the likes of AWS, Google, & Apple. Whilst they’ve given some back, there’s unlikely to be many commercial IT endeavours that don’t pay them some dollar.

    Looking forward, I wonder how far IT systems can be run within sovereign infrastructure? Germany and France seemed to take the ideal of open source more literally. Should we be looking to create home-based hosting; stop the transitions to the cloud of “just someone else’s server” – and work out how to stop the brain drain and commercial drain that is software licensing on European and British solutions.

    As we pick up more AI solutions that will be biased towards the status-quo; we’ve really got to make a determined and conscious effort if we want to break it – if it’s even possible.

  • Upgrading My Recovery: From Thumper to Theragun Mini

    I’ve made and maintained a positive start to the year when it comes to running & exercise.

    I’ve managed to get to the gym – two or three times a week. The lovely team at Format Fitness have been putting me through my paces.

    I’ve also joined a new run club @ the Byrds in Leytonstone. It’s at 7pm on a Tuesday night for a 5k run up to Whipp’s Cross and around Leyton Flats.

    It’s pretty good to be running regularly again, and even the 1°C run this morning was enjoyable.

    I’m also saying goodbye to my massage wand; Thumper – having upgraded to the Theragun mini. It felt like it was a super-luxury purchase. However, after some Achilles problems last year, it’s already paying dividends on loosening up my calves and hips. The associated app also provides some neat stretching routines after my runs.

    I’m adding more races to my calendar this year. I am growing in confidence. I’m very much looking forward to joining my “littlest” brother Charlie. We will take on the Manchester Half in October.

  • From disappointment to a solid start.

    The year didn’t quite start as I’d hoped it would.

    Instead of being able to do the fourth seasonal parkrun on New Years day – I was in bed with a bit of a head cold.

    Having got my exercise plan all laid out in TrainingPeaks, it was a bit disappointing to have to start 2025 in bed, resting up. I had to convince myself to take a long-term perspective and make sure I got over this illness before I started training.

    Well a few days later, the illness passed, and I got out to do my runs. The second week in Jan allowed me to hit 7/7 active days – 3 runs, 3 weight training sessions and a wonderful 7k walk with my dog Django yesterday.

    I do have a Garmin training plan telling me I should run; but it’s -1*C here today; my weekly mileage needs building up slowly – and this morning on the dog walk I saw a runner stack it on some ice (on trail, rather than tarmac). Today’s going to be a rest day, a bit of reflection – and I’ll pick up my training tomorrow.

  • New Years Resolutions

    Well, it’s another year and this blog is still pretty empty.

    I’ve got some events planned this year, so got the data dialled into TrainingPeaks to try and get myself organised. Despite having completed the half-distance Ironman last year, I didn’t feel like I could give it my all due to an achilles problem I picked up in training.

    After 10 weeks of rest, I managed to successfully complete all the hikes we did on our Honeymoon to Peru/Colombia without any further achilles pain. I also managed 3 of the 4 seasonal parkruns, and only missed NYD due to a cold, rather than being the incredibly hungover Andy I was on the 1st Jan 2024.

    Last year I completed dry Jan, and spent the year with a significantly lower alcohol consumption rate than previous years – definitely a good thing.

    So this year, I’m already committed to a 25k Canal path run on the 29th March, and a Olympic Triathlon in Belvoir Castle on the 29th July. Between then we’re also looking at a 25k trail run in the Aosta valley, to fit in with a pre-summer holiday this year.

    I need to take more breaks, relax a little bit and get the balance right between work, rest, and exercise. I’m also going to focus on my nutrition; whilst I don’t intend to calorie count or track my regular meals (I’m terrible at monotony) – I will be doing weekly reflections on how I’m doing.

    Helping me with this, I’ve recently discovered #LogSeq – and after the nice people on their discord channel gave me some pointers, I’m finding it a great way to keep the million things in my head organised.

    Here’s to 2024 – Happy New Year!

  • Back in the gym

    Alongside the triathlon training, today marked the first day back at my regular group personal-training gym.

    It’s a great little gym doing small-group personal training; which means a maximum of 4 people in a class doing multiple sets of a ‘breakfast, lunch and dinner’ program. Each meal has two/three exercises each, with multiple repeats.

    I’ve now been going for over two years (with two ‘month skips’) for holidays/wedding .etc; and I’ve really noticed a positive impact on my core strength and general health. Initially I was looking forward to losing a little bit of weight; but instead the focus has really been on holding my body better, and just feeling generally loads healthier when pottering about the house/garden and doing any weight-based chores.

    I would thoroughly recommend anyone wanting to get this sort of thing done as part of their regular exercise. I was initially a bit against waking up at 6.30 twice a week to make it to a 7am session – but now we’ve got in the groove I kinda missed it!