After having used docker for "real" things for the past 8 months or so, I definitely agree with you that it kinda sucks.
Docker's strengths come from the workflow you get to use when you use it... "Run /bin/bash in ubuntu" and it just works. For developers that's great. For a backend that does the heavy lifting for you when you're developing a lot of operations automation (like a PaaS), it starts to break down.
Just some of the things I've come across:
* Running a private registry is awkward. You have to tag images with the FQDN of your registry as a prefix (which is braindead) for it to "detect" that it's supposed to use your registry to push the image. "Tags" as an abstraction shouldn't work that way... they should be independent of where you want to store them.
* Pushes and pulls, even over LAN (hell, even to localhost) are god-awful slow. I don't know whether they're doing some naive I/O where they're only sending a byte at a time, or what, but it's much, much, much slower than a cURL download to the same endpoint. Plus if you're using devmapper then there's a nice 10-second pause between each layer that downloads. btrfs and aufs are better but good luck getting those into a CentOS 6 install. This is a major drawback because if you want to use docker as a mesos containerizer or otherwise for tasks that require fast startup time on a machine that hasn't pulled your image yet (ie. a PaaS), you have to wait far too long for the image to download. Tarballs extracted into a read-only chroot/namespace are faster and simpler.
* Docker makes a huge horrible mess of your storage. In the devmapper world (where we're stuck in if we're using centos) containers take up tons of space (not just the images, but the containers themselves) and you have to be incredibly diligent about "docker rm" when you're done. You can't do "docker run --rm" when using "-d" either, since the flags conflict.
* In a similar vein, images are way bigger than they ought to be (my dockerfile should have spit out maybe 10 megs tops, why is this layer 800MB?)
* The docker daemon. I hate using a client/server model for docker. Why can't the lxc/libcontainer run command be a child process of my docker run command? Why does docker run have to talk to a daemon that then runs my container? It breaks a lot of expectations for things like systemd and mesos. Now we have to go through hoops to get our container in the same cgroup as the script running docker run. It also becomes a single point of failure... if the docker daemon crashes so do all of your containers. They "fix" this by forwarding signals from the run command to the underlying container but it's all a huge horrible hack when they should just abandon client/server and decentralize it. (It's all the same binary anyway).
The other issues we've seen have mostly just been bugs we've seen that have been fixed over time. Things like containers just not getting network connections at all any more (nc -vz shows them as listening but no data gets sent or received), changing the "ADD /tarball.tgz" behavior repeatedly throughout releases, random docker daemon hangs, etc.
If as we're using docker for more and more serious things, we end up getting an odd suspicion that we're outgrowing it. We're sticking with it for now because we don't have the time to develop an alternative but I really wish it was faster and more mature.