[HN Gopher] Just say no to :latest
       ___________________________________________________________________
        
       Just say no to :latest
        
       Author : kiyanwang
       Score  : 193 points
       Date   : 2022-03-06 10:16 UTC (12 hours ago)
        
 (HTM) web link (platformers.dev)
 (TXT) w3m dump (platformers.dev)
        
       | erwincoumans wrote:
       | Same with pip/Python. Recucing dependencies to a bare minimum
       | helps long term survival of software.
        
         | paskozdilar wrote:
         | It also helps with reducing dependency distribution issues -
         | I've written single-file Python programs using just the stdlib,
         | sometimes of a really old Python3 version. It's really nice to
         | just `scp` the script to a bunch of remote devices and have
         | everything work out-of-the-box.
         | 
         | Of course, PyInstaller can solve dependency distribution issues
         | - but I've sometimes ran into packages that don't play well
         | with PyInstaller (uwsgi, for example, because it's basically a
         | C program distributed using pip, so PyInstaller can't figure
         | out how to bundle it).
        
         | ComradePhil wrote:
         | But it may hinder short-term survival (because you're spending
         | time reinventing the wheel instead of building competitive
         | product).
         | 
         | Lockfiles (poetry.lock, Pipfile.lock etc.) solve the
         | survivality problem for the most part.
        
           | izacus wrote:
           | > But it may hinder short-term survival (because you're
           | spending time reinventing the wheel instead of building
           | competitive product).
           | 
           | That's very rare. It's a common trope though and causes
           | amazing examples of startup companies self-destructing
           | themselves when they end up being bogged down in dependency
           | maintenance wars where they're spending a lot of time just
           | fighting all the issues in 100s of alpha libraries they've
           | put on to be "faster". The argument for that was always the
           | one you used. Adding a dependency isn't just "free code",
           | it's also "free code that will probably break at some time
           | and will need to be updated and deconflicted."
           | 
           | In my experience, a good set of older, tested and well
           | maintained core depdenencies is usually much better for
           | company, even if that means that they themselves maintain a
           | piece of functionality that exists as a library.
        
       | crucialfelix wrote:
       | Agree. I think it's better to explicitly update major versions
       | and know to keep an eye on the deployment in case it's something
       | that tests can't cover.
       | 
       | I had a CloudBuild fail to deploy due to a bug in one of the
       | builders :latest. Ironically the bug was due to a change in error
       | logging, so it failed silently.
       | 
       | So it's not just docker or dependencies.
       | 
       | In this case I could've used a GCP notify that the builder
       | failed.
        
       | keymone wrote:
       | # GOOD:         image: "nginx:1.21.6"
       | 
       | nothing "good" about it, literally no different from ":latest".
       | 
       | only full hash reference.
        
         | fuzzy2 wrote:
         | Sure version tags could also move, but by convention they do
         | not. Unlike the _latest_ tag, which by convention does move a
         | lot.
        
           | isbvhodnvemrwvn wrote:
           | By convention npm packages are not deleted or hijacked.
        
             | fuzzy2 wrote:
             | You do realize that NPM package versions already are
             | immutable? Dunno since when though.
             | 
             | Deletion is possible within limits but it also is with
             | Docker. All the hashes in the world won't bring back a
             | deleted image.
        
               | keymone wrote:
               | version numbers are never immutable. they are arbitrary
               | labels that are created by some centralized authority and
               | can be changed by that same authority.
               | 
               | artifacts being removed is much less of a problem as
               | artifacts being spoofed with malicious content.
        
               | isbvhodnvemrwvn wrote:
               | They were made immutable after the issue was already
               | widespread. Which is also why I'd heavily encourage to
               | use hashes to pin container versions, even though people
               | might not see the immediate need to do so.
        
         | delusional wrote:
         | From the original article
         | 
         | > This brings up an interesting side point, in that Docker Hub
         | and most other registries allow mutable tags by default. So
         | nginx:1.21.6 might not be the same image today as it was
         | yesterday. In reality, you probably need a mechanism to enforce
         | tag immutability: e.g., your own registry mirror, or referring
         | to images by SHA)
        
           | keymone wrote:
           | yeah, well, i stopped reading when i saw that "GOOD" example.
           | it's not. and that isn't a "side point", that's the most
           | critical point for preserving security and reproducibility of
           | builds.
        
             | delusional wrote:
             | It's literally the line that follows that example. Why do
             | you think it's useful to comment when you haven't even read
             | the topic of discussion. You're like a person not reading
             | the book at a voluntary book club. If you don't want to
             | read it, just don't show up.
        
               | keymone wrote:
               | i suggest you to read my comment again, because so far
               | what you've said applies to you more than to me.
        
             | zufallsheld wrote:
             | Well then you'd vendor your docker images anyway and not
             | pull them from the internet, right?
        
         | hughrr wrote:
         | Stuff like this makes me miss pinned RPM packages.
        
       | jahirul247 wrote:
        
       | jayzalowitz wrote:
       | Speaking as potentially one of the most prolific editors in tech
       | history, your wife was right for the wrong reason.
       | 
       | You needed your article to state an example where latest
       | dependency would kill a puppy.
       | 
       | Then your title is valid.
        
       | ashildr wrote:
       | There are containers that I want ASAP to be updated to the latest
       | version which likely contains all known security fixes. I
       | consider the risk of missing an update for a - then public -
       | security problem greater than the risk of getting a new, still
       | unknown security risk. While I am trying to, I will not have the
       | time to be really on top of all updates at all times. And I am
       | more comfortable with a container breaking than with a container
       | missing an important update.
       | 
       | There are aspects where reproducibility is key, but thats only a
       | subset of all containers on our network. And on my home network
       | it's none at all.
        
       | throwaway984393 wrote:
       | Eh. It depends. There are exceptions to every rule.
       | 
       |  _latest_ is useful for builds where you want to know when
       | something will break. If you only stick to pinned versions, it 's
       | common for nobody to ever update the pinned versions for years.
       | Then you're way behind the latest versions and suddenly upgrading
       | becomes a huge pain. You may be stuck in a situation where you're
       | forced to upgrade because of a security hole in your pinned
       | version, but to upgrade to a patched version breaks everything.
       | 
       | ".....But that's terrible!", you say. "My build won't be
       | repeatable! I won't be able to perform a roll-back build! My
       | build will constantly break!"
       | 
       | All of that is true, but there are workarounds. For example, if
       | you download, version, and store all artifacts used for each
       | build, you can reuse them later. This isn't hard if you take the
       | time to write some scripts. You can pull a container and export
       | it to a tarball and store it. System packages and language
       | dependencies can be downloaded similarly, and repos mirrored. You
       | can do this once a week and version all artifacts with a
       | datestamp, and make your own app builds pinned to a particular
       | datestamp.
       | 
       | If you always build from those versioned archived datestamps, you
       | can always rebuild or revert to an old working _latest_ build.
       | 
       | As far as builds breaking, they certainly will! You need good
       | testing to catch bugs and regressions. But would you rather learn
       | to adapt quickly to broken builds, or have a sleeping tiger
       | waiting to bite you the one time you finally have to upgrade
       | quickly?
       | 
       | Using a stable branch/tag is the safest hedge against frequently
       | breaking builds while still getting security patches. But stable
       | branches still introduce problems. You will eventually need to
       | revert a stable change, and eventually the stable branch will be
       | End Of Life. So even if you use stable, you should still use the
       | practice of installing from downloaded versioned artifacts.
       | 
       | Since EOL will come eventually, you also have to commit to
       | upgrading to a new stable branch and its breaking changes. You
       | must therefore plan to sunset your own code. Find out when your
       | dependencies will EOL, and plan to completely rebuild your apps
       | using _latest_ before then. It has to be a real commitment and
       | not just a  "nice to have", because you _will_ end up being
       | forced to do it by a security vuln or repos that stop carrying an
       | old branch.
       | 
       | Ultimately you need to decide how much risk to take and how much
       | planning is needed to avoid sticky situations. Be aware of the
       | consequences of your design and have contingency plans.
        
       | hpaavola wrote:
       | Use latest during development, but push to production using image
       | in your private Docker registry which has proper names and tags.
       | 
       | git push -> Docker build (bonus points for building only if
       | needed [for example only if Dockerfile, Jenkinsfile or
       | requirements.txt has changed], otherwise use latest from
       | Artifactory) -> run all automated tests -> if pass, push the
       | Docker image to Artifactory with reasonable name and tag.
       | 
       | When doing a release, push the image from Artifactory to
       | production.
       | 
       | This way you don't have to have a process to update all the
       | things in Dockerfile on reqular basis, but you still only push to
       | production the actual binaries that are really tested and proven
       | to be ok. And can re-use the actual binary when doing a hotfix of
       | something similar.
        
         | peakaboo wrote:
         | So what actually always happens with this approach is that
         | companies stay on ancient docker images, because there is never
         | time for updates as long as they work.
         | 
         | It's the same with locking python pip packages to specific
         | versions. Nobody ever looks at it again and you run code that
         | is 5 years old in production. People only look at it when it
         | breaks.
        
           | yardstick wrote:
           | At least they would have never upgraded to log4j 2...
        
           | hpaavola wrote:
           | I just said that use latest exactly to avoid this issue.
        
             | peakaboo wrote:
             | You said to use it for development. But I don't use
             | Artifactory so maybe you meant to use the latest for
             | production also, if it passes the build.
        
               | hpaavola wrote:
               | Having robust process requires some tools. Artifactory
               | (or any other private Docker registry) is one such tool.
        
       | snicker7 wrote:
       | Dockerfiles are generally bad for reproducibility. This is mostly
       | because Linux distros generally don't care about it. Nix and Guix
       | both support Docker export.
        
       | outside1234 wrote:
       | Going even further with this - it has always struck me that the
       | ALWAYS should be just be a hash of the docker image such that it
       | is essentially content addressed and can be verified on the
       | receiver end. Is there any reason that this isn't a good idea?
        
       | synergy20 wrote:
       | I agree. Or provide something in parallel such as:
       | :lts      -- newest long term stable release         :release  --
       | newest regular stable release         :x.y.z   --  supported but
       | you need find out the exact version each time!
        
       | ratherbefuddled wrote:
       | In practise using latest or just the major version has caused far
       | less wasted effort for our team than scrambling to update
       | versions because of some newly discovered CVE.
       | 
       | It's a problem in frontend builds because js libs are quite
       | poorly behaved so we fix more there but any backend stuff, be it
       | alpine / debian base images, jvm libs, toolchains so on we've not
       | had an issue with specifying only major versions.
       | 
       | Dogmatic rules are wrong 100% of the time.
        
       | KaiserPro wrote:
       | Yes, and no.
       | 
       | This does mean that you have to actively manage your versions for
       | any security fixes. Which you should be doing anyway. However
       | when upgrading or patching you have to check in a bunch of places
       | to make sure the update was effective.
       | 
       | As someone mentioned else where, its better to pin to major
       | versions rather than specific. You'll need to make sure you have
       | decent integration tests and monitoring though. I mean you have
       | that already right?
        
       | jacobr wrote:
       | People are mentioning that pinning versions lead to overhead in
       | updates. These people have probably not used Renovate
       | https://docs.renovatebot.com/
       | 
       | Renovate is smart enough to understand that a task such as
       | "Update Node to v16" means updating .nvmrc files, updating FROM
       | in Dockerfiles and engines in package.json in a single PR it
       | creates for you.
        
         | onedr0p wrote:
         | Renovate is amazing, and a tool most Developer and DevOps
         | engineers should learn. It's FOSS, and does a great job at
         | dependency management across a very wide range of software like
         | NPM, Terraform, Docker, Ansible, Maven, Golang, Rust and many
         | others.
         | 
         | https://docs.renovatebot.com/modules/manager/
        
         | cesnja wrote:
         | Renovate is great, far better than relying on somebody
         | remembering to upgrade dependencies in 12 different places.
         | 
         | But if you want full coverage, there will be a need to write a
         | few regex managers. And testing can only be done in production
         | on the mainline branch. The best way I found to do that was
         | forking the repo to configure and try out renovate separately.
        
       | Havoc wrote:
       | Depends on usage case. At home I :latest everything. The work of
       | constant adjusting tags to bring it up to date is more hassle
       | than the risk of something breaking.
       | 
       | Prod stuff....yeah best to pin it for supervised upgrades
        
       | 3np wrote:
       | Call me stuffy but I argue for writing your own Dockerfiles, all
       | from one or a small number of common base images (e.g.
       | scratch+debian, or what have you), served from your self-hosted
       | registry.
       | 
       | If you want to use some provided official image for vendored
       | software, just port it over.
       | 
       | Then you tie the build+push into your pipeline however suits your
       | org, be it fully manual or end-to-end CI with regular rebuilds.
       | 
       | This solves several issues mentioned elsewhere in the thread. As
       | a bonus you won't be affected should docker.io or quay have
       | issues or make breaking changes.
        
       | saulr wrote:
       | Worth noting that Hadolint[1] raises warnings the issues
       | mentioned in the article. Some examples of warnings:
       | 
       | - https://github.com/hadolint/hadolint/wiki/DL3007: Using latest
       | is prone to errors if the image will ever update. Pin the version
       | explicitly to a release tag. -
       | https://github.com/hadolint/hadolint/wiki/DL3013: Pin versions in
       | pip. - https://github.com/hadolint/hadolint/wiki/DL3018: Pin
       | versions in apk add.
       | 
       | [1] https://github.com/hadolint/hadolint
        
         | ievans wrote:
         | Hadolint is great! If you want to customize your lint logic
         | beyond the checks in it, I recently wrote a Semgrep rule to
         | require all our Dockerfiles to pin images with a sha256 hash
         | that could be a good starting point:
         | https://github.com/returntocorp/semgrep-rules/pull/1861/file...
        
       | ComradePhil wrote:
       | Terrible advice.
       | 
       | It doesn't solve the "immutability" problem and may give you a
       | false sense that it does, which is a much bigger problem.
       | 
       | Here's the "good" example from the article:                   #
       | GOOD:         image: "nginx:1.21.6"
       | 
       | Here is the header of the source of the Dockerfile for this
       | image:                   FROM debian:bullseye-slim
       | LABEL maintainer="NGINX Docker Maintainers <docker-
       | maint@nginx.com>"              ENV NGINX_VERSION   1.21.6
       | ENV NJS_VERSION     0.7.2         ENV PKG_RELEASE     1~bullseye
       | ...         ...         ...
       | 
       | Notice the first line? `debian:bullseye-slim` is not "immutable".
       | Should the `nginx:1.21.6` image auto-update when new
       | `debian:bullseye-slim` is available? Or should it keep it what it
       | was during the build time? I am not exactly sure how nginx does
       | it but it would not be incorrect to do either (both address
       | different issues and are completely valid depending on what you
       | want to do).
       | 
       | If you are serious about using docker, you need a private
       | registry and you need to make a tagging policy that is best for
       | YOUR use-case.
        
       | [deleted]
        
       | [deleted]
        
       | bombcar wrote:
       | With a bit of work you can run with pinned versions that act like
       | :latest - in the equivalent gradle scripts we have explicit
       | dependencies but we have another script that updates them to
       | whatever is _actually_ the latest at the time.
       | 
       | So it's like master-SNAPSHOT when we need it to be, but still
       | with reproducibility and regular updates.
        
       | raffraffraff wrote:
       | I somewhat agree. But it's not that simple in practice. For
       | example, I pin every single version and the container fails a
       | security scan because it's not using latest versions of
       | everything. Or I pin to arbitrary versions that happened to be
       | latest when pip/npm/terraform first created the precious word-of-
       | god lock file, leaving future engineers afraid to upgrade those
       | packages because "Chesterton's Fence".
       | 
       | Pinning versions creates work in the future. Using latest
       | versions can result in ad-hoc breakages and security risk. So
       | instead of saying "v1.22=good, latest=bad" and talking generally
       | about the fact that lock files exist in most decent systems, I'd
       | like an article that contains example strategies for paying back
       | the tech debt of a thousand arbitrarily pinned versions across
       | your code projects.
       | 
       | I like the idea of deleting the lock file on a regular cadence,
       | accepting whatever new shit comes in, perhaps bumping a major
       | version number, and then testing the crap out of everything and
       | leaving this new _artifact_ in integration /staging for a few
       | extra days. If things go wrong between builds, then you have the
       | lock files in git (and in your artifacts) to let you know what
       | changed. If it turns out that you now have a _real_ reason to pin
       | a specific package (ie: it broke something), then you have to
       | find some way to note that outside of the usual lock files, since
       | they arbitrarily lock everything.
        
         | mr_tristan wrote:
         | Pinning can be far less painful with tooling to review and
         | manage all the changes. One example would be the Maven versions
         | plugin: you can use it to query "what's been updated", update
         | to next release, etc. The list of goals is pretty explanatory,
         | and a good starting point: https://www.mojohaus.org/versions-
         | maven-plugin/
         | 
         | When evaluating new toolchains, I often ask myself "what is the
         | versions plugin equivalent here". There's often commercial
         | offerings that help this process out.
         | 
         | Dependency management is one of these topics that rarely gets
         | attention until much later in the ecosystem's lifetime. So
         | chances are you'll need to find or create tooling to fill gaps.
         | 
         | I mean, you can do the whole "damn the torpedos and see what
         | breaks" approach, but, I'd prefer a way to review changes. And
         | I'd prefer doing those updates _separate_ from other changes.
        
         | 88913527 wrote:
         | Needlessly upgrading all of your packages leaves you open to
         | supply chain attacks. If one of those NPM packages got quietly
         | compromised (and my lockfile likely has 4-to-5 digits worth of
         | dependencies in it), you invested time in making what amounts
         | to an unneeded change to expose yourself.
        
           | raffraffraff wrote:
           | Ok, so let's say it's day one: how do you choose all of your
           | initial pinned versions? How do you know they're safe? What
           | if you luck-out in the supply chain attack lottery and pin
           | malware?
        
           | duped wrote:
           | The only real defense to supply chain attacks are audits and
           | self hosted dependencies/packages.
        
             | roblabla wrote:
             | > self hosted dependencies/packages.
             | 
             | Why? If your lockfile specifies and enforces the hash of
             | the package, you don't need to self-host it - the lockfile
             | will take care of detecting supply chain compromises that
             | swaps a package with another.
             | 
             | 100% agree on audits being necessary.
        
               | charcircuit wrote:
               | Self hosting protects against attacks against the
               | availability of your supply chain.
        
         | lamontcg wrote:
         | You need to have a CD system which takes equality pinned deps
         | and bumps them when new versions come through and automatically
         | runs the new versions through whatever your
         | test/integration/production environments looks like. And you
         | should have sufficient integration testing that you should have
         | confidence that an automated process should be able to decide
         | if the new version should get deployed to prod (being realistic
         | you probably want to confine these deployments to some sort of
         | reasonable business hours).
         | 
         | Then the tech debt gets addressed automatically without any
         | work. The work is all up front to write the tests that give you
         | confidence about deployment to production, but that is work
         | that needs to happens and pays off. You shouldn't need to have
         | human testing in the loop.
        
           | crummy wrote:
           | Do people have automated tests to validate their SMSs are
           | sent correctly (and received by a real phone)? Or that credit
           | card payments are made correctly? These are things I use
           | third party libraries for, and what I worry might break when
           | I upgrade dependency versions.
        
             | adenner wrote:
             | Depends, how big of a deal is it when they break?
        
             | sbierwagen wrote:
             | Most payments vendors will have test CC numbers for
             | integration testing. One of Paypal's test numbers is
             | 5555555555554444, for example.
             | https://developer.paypal.com/api/nvp-
             | soap/payflow/integratio...
        
           | raybb wrote:
           | I haven't used it myself but I'm pretty sure Whitesource
           | Renovate is free tool that tries to do just that.
           | 
           | https://www.whitesourcesoftware.com/free-developer-
           | tools/ren...
        
             | throwanem wrote:
             | Weird, I thought it was a tool for encouraging engineers to
             | learn how to use Github PR search filters.
        
           | humanrebar wrote:
           | Agreed. There are logical, version-flexible dependencies. And
           | then there are rigid, version-specific dependencies.
           | 
           | Robust systems need to model both so they can support
           | reproducibility _and_ automation needs.
        
         | armchairhacker wrote:
         | Pinning versions creates future work but so does using the
         | latest version.
         | 
         | Vulnerability discovered in old version vs. vulnerability
         | maliciously inserted in new version; software engineers afraid
         | of upgrading because of breaks vs these breaks actually
         | occurring because of an unexpected upgrade.
         | 
         | I personally prefer pinned versions because whenever I try to
         | install some old github example or other code, I usually end up
         | getting stuck with errors _unless_ everything (compiler,
         | dependencies, etc.) are pinned. Gradle projects almost always
         | work no matter how old (Gradle pins the dependencies, JVM, and
         | even the version of Gradle), whereas npm and CMake projects
         | (which are built with new compilers and usually new
         | dependencies) often fail.
        
       | oxfordmale wrote:
       | This is always a balance. The moment you pin to a specific
       | version you need to have a process in place to ensure you
       | regularly upgrade to avoid introducing vulnerabilities in your
       | production system. Throughout my career I have seen many cases
       | where certain software still runs on ancient versions as the team
       | originally maintaining it is no longer around (e.g.
       | reorganisations or lay-offs). It is always hard to convince
       | senior management to invest any resources to upgrade (If it works
       | don't fix it)
       | 
       | If I have project that has good unit test coverage, I prefer to
       | use :latest, as this results in a gradual update over time. If
       | something breaks due to a version discrepancy, it is a lot easier
       | to convince management to fix this, as the breakage would only be
       | noticed as part of a feature request, and often would only
       | require a small amount of work.
        
         | KronisLV wrote:
         | I'd say that there are two things that you should have in place
         | regardless of which approach you take:                 - having
         | tests (or even manually test the system with scenarios, if for
         | whatever reason you cannot automate) in place to catch things
         | breaking, before shipping any changes       - having security
         | scanning in place, be it for containers, your dependencies, or
         | anything else; ideally for everything
         | 
         | Then, things should get a bit more clear:                 - you
         | should be able to spot the publicly known vulnerabilities and
         | adequately evaluate their impact to decide what must be done
         | - when you update versions of your dependencies, you should
         | then also be able to see whether anything breaks before
         | shipping
         | 
         | Admittedly, all of that will only be viable if you have the
         | buy-in from the people involved, since otherwise you'll get
         | "blamed" for things breaking as a result of your initiative for
         | avoiding shipping vulnerable software, or you'll find it
         | difficult to justify to people why you're spending so much time
         | updating dependencies and doing refactoring.
         | 
         | Not only that, but some systems out there are not really easily
         | testable, e.g. those that have a large amount of functionality
         | within the DB so your tests might as well end up mocking either
         | too much of the system or the wrong parts of the system (i'm
         | yet to see anyone mocking the low level queries that go to the
         | DB and back, e.g. setting and validating the individual
         | parameters within query abstractions, as opposed to just the
         | data that's returned) - in many cases it simply won't be viable
         | to test everything.
         | 
         | Another thing is that in practice semver tends to lie to us and
         | even minor updates or patches can sometimes have breaking
         | changes within them, something that i wrote about in my blog
         | article "Never update anything":
         | https://blog.kronis.dev/articles/never-update-anything (albeit
         | there i also touch upon the fact that software should largely
         | be more stable and have fewer breaking updates in the first
         | place, or even less new features in "stable" branches)
         | 
         | I guess my argument is that there's a lot of complexity to be
         | tackled here and that people should invest more time and effort
         | into handling updates, refactoring and even testing, than they
         | do now: i've seen teams where people all agree that tests are
         | important, yet nobody wants to write any because if they tried,
         | they'd have to mock large parts of the system OR try to do
         | integration tests and handle the fact that nobody has invested
         | the time and effort into bringing up reproducible environments
         | and services, e.g. a new automatically migrated DB instance for
         | the tests OR the fact that they'll need to do tests in a shared
         | DB instance and clean up afterwards. Environments like that are
         | just a downwards spiral that's bound to produce brittle
         | software.
         | 
         | So what's my practical advice?
         | 
         | Use pinned versions, preferably starting with the latest and
         | most boring one that you can get away with (e.g. LTS). Have a
         | process in place for figuring out when you need to update, set
         | aside time for doing just that (even if manually), assign
         | someone to do this and someone else to make sure it's been
         | done. Have testing and serious validations be a part of this
         | process, to make sure that there's no breakage that'd slip past
         | - full regression testing, all your unit tests, integration
         | tests, feature tests etc. How often should you do it? Depends
         | on the importance of the system - i've seen it done quarterly,
         | i've seen it done monthly, some with plenty of resources out
         | there could probably do it weekly or more often. Additionally,
         | be able to do this ASAP when critical vulnerabilities become
         | apparent, e.g. log4shell.
         | 
         | Of course, it's the ultimate example of useful but exceedingly
         | boring work that people don't really want to do, so i've no
         | doubts about running into unmaintained software in the future.
        
         | peakaboo wrote:
         | I've also seen the same. As soon as people start locking
         | versions, that code is no longer updated and nobody will change
         | it, because it's extra work to do so.
         | 
         | I personally think running latest is the best thing to do. And
         | if something fails, you downgrade it temporarily until the
         | latest work again. It's pretty much opposite to what is
         | recommended, and it's just the best solution in my opinion.
        
           | bspammer wrote:
           | My company locks versions, but dependabot is configured on
           | all of our repos. It automatically creates PRs to bump
           | versions, and if CI passes for minor/patch bumps they get
           | automatically merged. This takes a lot of the hassle out of
           | the problem. For major bumps, a manual approval is required,
           | but they happen infrequently enough that it's not a lot of
           | work.
        
             | ipsocannibal wrote:
             | A similar tool to dependabot written by Salesforce:
             | https://github.com/salesforce/dockerfile-image-update
        
         | yardstick wrote:
         | Doesn't the same logic apply to using :latest? If you are
         | always pulling the latest, unvetted, code, shouldn't you also
         | have a vulnerability management process in place?
         | 
         | You need vulnerability & risk management for any dependency,
         | full stop.
        
           | oxfordmale wrote:
           | Ideally you only use Docker official images,or their
           | equivalent to avoid using unvetted code.
           | 
           | It is always a trade off, however it is far more likely that
           | a hacker will use a ten year old well exploited CVE, rather
           | than a recent one
        
             | yardstick wrote:
             | I wouldn't describe Docker official images as more or less
             | secure than anything else. Supply chain attacks can easily
             | slip a vulnerability in.
        
             | laumars wrote:
             | > Ideally you only use Docker official images,or their
             | equivalent to avoid using unvetted code.
             | 
             | Docker images don't ship every dependency in the average
             | development project. They're also not a security guarantee
             | either.
             | 
             | > It is always a trade off, however it is far more likely
             | that a hacker will use a ten year old well exploited CVE,
             | rather than a recent one
             | 
             | In general that's the case but in practice that's still the
             | wrong mindset. You pin to a minor version and still get
             | patch updates. Or run CVE checks to prove you're
             | dependencies have no reported vulnerabilities. And that
             | will also mitigate the risk of you again accidentally
             | updating to to new vulnerabilities (though you'd need to
             | pin against patch version too if you want to be certain
             | there)
        
               | oxfordmale wrote:
               | I have seen many cases where a something is pinned to a
               | minor version, and then gets forgotten about for 2 or 3
               | years. In my current companies there is Production
               | codebase that hasn't been touched for over two years. The
               | original developers have long since moved on and no one
               | really owns the code. That is the most common scenario
               | leading to security breaches.
               | 
               | This is about succession planning, with the realisation
               | there might not be any succession if business priorities
               | change.
        
               | yardstick wrote:
               | In that case, better the devil you know? But either way
               | if you don't have a vulnerability management plan you are
               | at risk.
        
         | speed_spread wrote:
         | Covert maintenance is the name of the game. If the site goes
         | down because of a security flaw you'll be blamed anyway. Might
         | as well get fired for doing the right thing.
         | 
         | I'm only half joking... The right thing to do with dummy
         | management is to get everything in writing to make it clear
         | that if anything happens it'll be their fault.
        
         | jenscow wrote:
         | Right. Let's assume you're going to need to upgrade sooner or
         | later - the longer you leave it, the harder it gets.
         | 
         | Best to upgrade and discover dependency issues during
         | dev/staging, than try to fix many months worth of them when
         | there's an active CVE on your live pinned version.
        
         | pojzon wrote:
         | Its hard to convince management that them adapting devops means
         | they actually have to follow devops principles.
         | 
         | Too many times Ive seen companies throwing this buzzword around
         | without understanding how much work is actually required to
         | have real devops.
        
           | cube00 wrote:
           | :s/devops/agile/g
        
         | paskozdilar wrote:
         | In that case, it's better to just pin the major version of the
         | container:                   FROM python:3
         | 
         | will work as long as Python3 doesn't make any backwards
         | incompatible changes (note: Python3 occasionally deprecates
         | then removes a feature that was part of the official API[0], so
         | Python3 is not technically semver-correct).
         | 
         | If, however, one wants automatic updates WITH reproducible
         | builds, then a CI/CD pipeline that automatically updates the
         | FROM line in a Dockerfile on every upstream release is an only
         | solution.
         | 
         | [0] https://docs.python.org/3.10/whatsnew/3.10.html#removed
        
           | thejosh wrote:
           | this works great until a library decides it only likes python
           | 3.8 or 3.9 or 3.10 and won't work with 3.10.
        
           | Kwpolska wrote:
           | Python never claimed to be semver-compliant. Also, if you're
           | using 3rd-party packages that require compiling stuff (eg.
           | numpy), pre-built binary packages (aka wheels) might not be
           | available on PyPI in the first few days (or weeks, or
           | sometimes even months) after Python 3.x.0 is released, so you
           | don't want the version to be randomly changed under you.
           | Moreover, I pulled python:3 a year ago, so I get 3.9.
           | 
           | FROM python:3.10 should generally be fine though.
        
           | oefrha wrote:
           | This is very bad advice. Lots of nontrivial things aren't
           | automatically compatible with the latest Python minor
           | version. PyTorch for instance doesn't support Python 3.10 and
           | it's been five months since the stable release (ten months
           | since the first beta). For anything nontrivial, you almost
           | always want to specify a minor Python version.
        
             | [deleted]
        
             | paskozdilar wrote:
             | Why is this bad advice?
             | 
             | The PyTorch scenario is an exception, not the rule, and the
             | users of PyTorch should know not to use unsupported
             | versions.
             | 
             | > For anything nontrivial, you almost always want to
             | specify a minor Python version.
             | 
             | Depends on how you define "trivial".
        
               | chomp wrote:
               | It's non-optimal advice because PyTorch is not the only
               | library that runs into problems like this, because Python
               | does not follow semver. You should pin to an X.Y release,
               | and let .Z releases update automatically (which is where
               | your security updates fall)
        
         | ReactiveJelly wrote:
         | It's better to only change one thing at a time, not to get your
         | dependencies updated as a surprise when you're trying to update
         | something else.
         | 
         | Besides, if the dependencies aren't pinned in version control,
         | how can you answer a query like "On this date last year, what
         | version were we running?"
        
           | oxfordmale wrote:
           | I am using AWS ECS as a Docker repo with releases using the
           | image hash (as well as a server). If you want to rollback to
           | a certain time, you just identify the appropriate Docker
           | image tag, and restore the Docker you used at that time in
           | your development environment.
           | 
           | To give an example, we got stuck on Python Pandas 0.24.2 for
           | two years when the Pandas 1.0 upgrade happened. At the time
           | we pinned the version as one job was failing. With COVID
           | priorities naturally changed and this was forgotten. When
           | normality returned we suddenly had to upgrade 10 jobs to
           | Pandas 1.2.x, a very painful migration that took one Engineer
           | 4 weeks of testing. In hindsight it would have been far
           | better to upgrade this one job, as it would have only taken a
           | few hours.
           | 
           | Again it is a trade off. Having unexpected dependency changes
           | can be cumbersome when you are releasing a small change.
           | However, getting senior management to agree of weeks of
           | upgrade testing can be challenging as well. My natural
           | preference is not to pin versions, unless I absolutely have
           | to.
        
         | EdwardDiego wrote:
         | I've used Maven version ranges to great effect... ...only
         | projects that actually observe semver.
         | 
         | (Jackson, take a bow for doing so with your patch releases. I
         | wouldn't use it for your 'minor' releases though.)
        
           | cuteboy19 wrote:
           | Maven versions are not present in VCS if you use ranges.
           | Wouldn't this cause issues like not know what Library version
           | is being used in production and builds not being
           | reproducible?
        
             | isbvhodnvemrwvn wrote:
             | Not to mention that Maven doesn't have any mechanism for
             | locking in transitive versions, because typically everyone
             | uses hardcoded patch versions and never update them.
        
               | EdwardDiego wrote:
               | How do you mean? You can override versions of transitive
               | dependencies.
        
             | EdwardDiego wrote:
             | That's true, but you can export resolved dependency
             | versions at build time if necessary. I've rarely used
             | version ranges because, well, semver rarely occurs, but for
             | Jackson, allowing it for patch releases was a decision to
             | ensure security updates were automatically picked up.
        
       | jbverschoor wrote:
       | :latest sounds like npm without lockfiles.
        
       | [deleted]
        
       | tlarkworthy wrote:
       | If you don't use latest, your ecosystem fragments and risks
       | diamond dependencies. If you do use latest, some of your
       | ecosystem risks randomly breaking.
       | 
       | I think it's best to use latest because the combinatorics of the
       | ecosystem as a whole is much smaller. With everything on latest,
       | you have to play whack-mole on individual services to get them to
       | catch up. But you are doing this just when the community at large
       | is most invested in understanding the process of upgrading.
       | 
       | The alternative is that ancient binary A depends on ancient
       | binary B's legacy behaviour, and B has no need to upgrade but A
       | have a very serious need and now you have a serious problem.
       | Maybe upgrading B breaks C for instance. It's almost
       | uncoordinateable at that point once versions drift significantly.
       | You get true technical debt.
        
       | c7DJTLrn wrote:
       | Pinning image tags is only useful if the upstream doesn't keep
       | retagging images. I've had a case in the past where a vendor has
       | retagged an image and broken something.
       | 
       | Maybe we should even be pinning to a specific layer/checksum like
       | so:                 FROM ubuntu@sha256:8ae9bafbb64f63a50caab98fd3
       | a5e37b3eb837a3e0780b78e5218e63193961f9
        
         | addingnumbers wrote:
         | The article covered that five paragraphs in:
         | 
         | > In reality, you probably need a mechanism to enforce tag
         | immutability: e.g., your own registry mirror, or referring to
         | images by SHA).
        
       | neonate wrote:
       | https://archive.ph/XeoiH
       | 
       | http://web.archive.org/web/20220306110425/https://platformer...
        
       | thenerdhead wrote:
       | The age old question is "How quickly do you update?"
       | 
       | Too slow - Exposed to known vulnerabilities.
       | 
       | Too fast - Susceptible to active supply chain attacks.
       | 
       | There's tradeoffs, and there's no solution here. It's a hard
       | problem.
        
         | ziml77 wrote:
         | Not just from a vulnerability poerspective but also a dev and
         | testing perspective. Constant updates makes testing far more
         | involved for every release since you can't just focus on the
         | parts the dev work would have affected, you also need to
         | thoroughly test everything that was calling into the updated
         | dependency. But if you don't update enough, once you really do
         | need to update either for security or feature reasons, you may
         | have a nightmarish process ahead of you of dealing with
         | breaking changes and transitive dependency incompatibilities.
        
         | lbriner wrote:
         | Exactly this. The OP reads like a nice perfect world scenario
         | but...
         | 
         | 1) Just because there is a vulnerability in a package of
         | library doesn't mean that you are susceptible to that
         | vulnerability 2) If you don't update immediately when will you?
         | Most companies can't afford people to understand all posted
         | vulnerabilities to work out whether updating is better than not
         | updating
         | 
         | The truth is there are easier ways to reduce risk than
         | pretending that a pinned version somehow solves a lot of
         | problems: Reduce your codebase/dependencies and apply defence-
         | in-depth.
         | 
         | Reproducability is something for some companies but, again, I
         | doubt there would be many times that I would care about what
         | exactly was deployed 6 months ago. If something is broken now,
         | it gets fixed now.
        
           | bigfudge wrote:
           | I really like Microsoft's mirror of CRAN because it's
           | versioned by date- you can install everything as it was on a
           | particular date, so that kind of reproducibility is easy. I
           | wonder if this could be added to pypi
        
       | timost wrote:
       | Maintaining docker containers up to date can quickly become time
       | consumming compared to good old distribution packages. I use both
       | and I'm still trying to find a good combination of tools to
       | reproduce the "package" and unattended upgrades UX where things
       | are safely kept up to date automatically.
        
       | bee_rider wrote:
       | It seems kind of weird that we don't do "stable repositories"
       | anymore.
        
       | charcircuit wrote:
       | >It breaks one of the core requirements of continuous delivery:
       | reproducible, idempotent builds
       | 
       | As long as you are able to look up what latest evaluated to
       | during the build you retain most of the benefits while getting
       | automatic updates.
        
       | ipsocannibal wrote:
       | I think this is an X/Y problem. The problem isn't pinning to
       | latest. The problem is lack of automation that makes builds
       | reproducable. In at least one FANG company I've worked for if you
       | aren't building from latest no one will listen to your issue. Too
       | much software changes to quickly to be pinning to specific
       | versions. However, the build system keeps track of the build
       | audit details and can rollback any build to any state. Teams are
       | required to add the necessary layers of unit, integration,
       | stress, crush, and chaos testing to validate each build. Its not
       | cheap but when you need to do a monthly firedrill of 'emergency
       | update this dep because of Z vulnerability' its worth it.
        
       | solatic wrote:
       | Forget for a second the security concerns -
       | 
       | If you lose :latest, and the build breaks, you need to spend
       | _unexpected_ time fixing the build, for whatever reason that
       | :latest broke it, in order to continue with the business
       | objective that you were actually tasked to do. Essentially, you
       | have InfoSec muscling in and demanding, by the most coercive way
       | possible, that Thou Shalt Not Do Your Job Without Bowing Before
       | Me. Who cares what the business wanted? Who cares about
       | predictable schedules? Who cares about delivering for a customer
       | by a point in time which was promised to the customer?
       | 
       | This isn't the way to promote a healthy culture in the company.
       | Nobody should get immediate and total veto rights. In the real
       | world, healthy organizations balance between different
       | stakeholders, and once a path is set, everybody shuts up and
       | executes. The right place to make a stand for your interests is
       | in the stakeholder meeting, not the deployment pipeline.
        
         | oxfordmale wrote:
         | My default workflow is not to the pin the version. The build
         | will only break occasionally and is often trivial to fix. In
         | the rare case it does require significant amount of work, and
         | management is breathing down your neck, you do temporarily pin
         | the version to get out the release, and create a backlog ticket
         | to resolve this as soon as possible.
         | 
         | This workflow ensures any work for minor version upgrade is
         | part of the development workflow. PMs can't deprioritise this
         | work against more exciting shiny product features. If you
         | include this as separate development tickets, it just tends to
         | get deprioritised until it becomes a big chunk of work.
        
           | solatic wrote:
           | > This workflow ensures any work for minor version upgrade is
           | part of the development workflow. PMs can't deprioritise this
           | work against more exciting shiny product features. If you
           | include this as separate development tickets, it just tends
           | to get deprioritised until it becomes a big chunk of work.
           | 
           | Instead of your maintenance work being visible, you're hiding
           | it. You're describing an adversarial culture, one where you
           | need to do shadow work because you don't trust management to
           | prioritize necessary maintenance, perhaps one where
           | management doesn't trust engineering to place maintenance in
           | its proper context. I don't think this is an ideal, I think
           | this is sad.
        
             | oxfordmale wrote:
             | I am not hiding it, I make it integral part of the
             | development process, as it should be. Treating technical
             | debt as a separate work item is asking for problems.
        
         | ashildr wrote:
         | > you have InfoSec muscling in and demanding, by the most
         | coercive way possible, that Thou Shalt Not Do Your Job Without
         | Bowing Before Me.
         | 
         | InfoSec is not optional.
        
           | solatic wrote:
           | Of course it's not. But it's not King, either.
        
             | jimmydorry wrote:
             | I could see it argued that in $CurrentYear, any information
             | oriented company that doesn't put InfoSec as their #1
             | priority, is just asking to be pwned. It's not an if, but a
             | when and to what extent.
        
               | izacus wrote:
               | No, #1 priority is always doing core business - the job
               | that gets money in, satisfies users and keeps the company
               | running. Everything else comes after - without core
               | business, infosec is pointless and can't sustain itself.
               | 
               | InfoSec is critically important, but it's important just
               | like IT people, janitors and server maintainers -
               | business breaks without them, but they aren't actually
               | earning money and prioritizing them over core business is
               | the tail wagging the dog.
               | 
               | (And yes, I've seen way too much entitled "InfoSec"
               | experts explicitly undermining their own company because
               | they forgot that. Read The Phoenix Project or similar for
               | concrete examples.)
        
               | falcolas wrote:
               | > they aren't actually earning money and prioritizing
               | them over core business is the tail wagging the dog.
               | 
               | Uhm, InfoSec helps prevent your company from hemorrhaging
               | money and trust in the form of fines and lawsuits. That
               | makes them a touch more important than you make them out
               | to be.
               | 
               | The bigger a companies customers are, the more important
               | InfoSec becomes to your "core business", because the
               | certifications and security required by those customers
               | have large infosec requirements.
        
             | falcolas wrote:
             | If you're fedramp certified, they kinda are. Fedramp is the
             | key that unlocks a lot of really high-paying customers, and
             | if you lose your certification those customers (with their
             | firehose of revenue) go poof.
             | 
             | How to lose certification: Don't address a known
             | vulnerability (CVE) within a specific number of days, based
             | on severity. Doesn't matter if it's log4j or some random
             | executable in your images that's never used.
             | 
             | When you're up to hundreds of services, thousands of
             | packages, and millions in revenue from Fedramp customers,
             | InfoSec gets pretty important.
        
               | solatic wrote:
               | FedRAMP also requires you to explicitly give veto power
               | to InfoSec at every stage of design, development,
               | implementation, operation, and maintenance, and to employ
               | a Change Control Board (CM-03).
               | 
               | There's only ~250 companies / products that are
               | Authorized at any level of FedRAMP, and many of them are
               | explicitly "Federal" versions of their products in order
               | to isolate the organizational controls away from
               | affecting their commercial offerings.
        
         | izacus wrote:
         | This! It gets even better - there WILL be a time at your
         | company when you'll need to revert for whatever reason. That
         | reason will most likely be something VeryImportant(tm) and will
         | probably have to be done RightNow(tm) on weekend if you're
         | unlucky.
         | 
         | At that time, you REALLY don't want to find out that you forgot
         | to pin your dependencies and that your older build now doesn't
         | run due to breaking changes and you have no frigging idea what
         | versions of that random NPM crap library were you running 5
         | weeks ago.
         | 
         | Just... don't do that to yourself. Ever. Pin dependencies,
         | update them regulary, but update them as YOUR decision under
         | YOUR CONTROL. Not under some techbros control based on his
         | GitHub pushes. If you're smart, also host your own repository
         | (Maven, Npm, Docket, whatnot) with your dependencies so your
         | business can't be distrupted by some techbro drama and missing
         | packages.
         | 
         | (This is one of those lessons old neckbears learned on their
         | own skin.)
        
       | sascha_sl wrote:
       | > In reality, you probably need a mechanism to enforce tag
       | immutability: e.g., your own registry mirror.
       | 
       | Ah, that sounds so trivial. And yet it is very much not. Aside
       | from the hot mess that is the docker registry daemon, some tags
       | are meant to be rolling. You absolutely do not want them cached.
        
       | bearjaws wrote:
       | The security questionaires we have to perform for our larger
       | customers now include that we pin the exact hash of a container
       | or mirror any image locally. This is in addition to pinning
       | versions of NPM packages and using our package lock for
       | installation.
       | 
       | We now have a basic rule that :latest doesn't make it past proof
       | of concept stage.
       | 
       | This has made automation of our package & container maintenance
       | crucial, since we are a lean shop. It's pretty much a weekly
       | occurrence that a low-medium vulnerability pops up somewhere once
       | your application is large enough.
        
       | Jhsto wrote:
       | In a perfect one would use CRIU [0] to suspend the old container,
       | then download the new one and start it. If the service comes up
       | with the new container, then remove the suspended one and
       | otherwise, fallback to the suspended container.
       | 
       | [0]: https://criu.org/Docker
        
       ___________________________________________________________________
       (page generated 2022-03-06 23:01 UTC)