* Leading to: inheritance for construction. Lots of images include a bunch of irrelevant material because it was easier to FROM an existing image than to tease apart the kitchen-sink into the brittle hierarchy.
* Meaning: using composition isn't really "a thing" in the sense that it's commonly used. I'm given to understand that OCI layers can, if you recalculate the hashes, be layered in arbitrary order. In an ideal world the build tool can check that there won't be layer conflicts, meaning you can treat layers as immutable mixins, rather than immutable parents. Instead of FROM, you could have UNION or PLUS.
Then of course the less abstract stuff:
* Mystery meat. Dockerfiles make development solely responsible for managing all dependencies from the OS up. An awesome tool and a problematic responsibility. You've graduated from worrying about XSS holes in your web framework to fretting about kernel bugs and glibc glitches. Where I work we have an entire team devoted to tracking CVEs that affect code we ship. Do you?
* Mystery meat, at scale. Now you have 5,000 containers running ... what, exactly? What versions of what OSes? Are the runtimes up to date? You're going to need to either rigidly control Dockerfiles -- in which case, what did it buy in terms of dev flexibility? -- or you're going to need to buy tools to scan all your images. Docker sells such a service, as it happens.
Dockerfiles are a simple, clean exposure of the original concept of layered FSes, processes and ports. But they are not without limitations.
Disclosure: I work for Pivotal, we compete with Red Hat and Docker in the PaaS space.