Part of this is Lisp-only history, outside of old Lisp users dynamic scoping really has few friends although the somewhat similar environment variable mechanism is widespread and accepted:
https://en.wikipedia.org/wiki/Scope_(computer_science)#Histo...
Yeah, “12 factor apps” basically use dynamic scope for dependency injection. But, also, I believe the Reader typeclass in Haskell is basically equivalent to dynamic scope? Haskellers seem to use this and a lot of similar techniques (Free monads/mtl style) to work around the lack of dynamic scope :).
Reader is similar, but I wouldn't say equivalent, because only those things working in the Reader can use that environment. For example, when you have project A using project B using project C, you can't define a putStrLn such that project C can use it and be able to override its output stream from project A, while keeping B completely ignorant of that ability of putStrLn or that C even uses putStrLn.
Reader is like a middle-ground between dynamic-scoping and explicit passing of a context argument around as you would in a statically-scoped language.