I’ve been using Docker for a while now and I’m constantly finding new and interesting use cases. File this one under ‘quick and dirty’, but I’ve gotten a lot of mileage out of it.

When running Docker in production, there is almost no reason to install software directly on the host. Once you have containerized your application, it can be run anywhere that Docker is available. All of this is great. Your application is portable and life is good.

But what about all of that software that you used to have convenient access to? Tools like pg_dump and pg_restore used to be installed directly on the host. What do you do when you want to run a one-off task?

Well, we could install them. But that wouldn’t be much fun. Let’s use more Docker!

Disclaimer: The following code was written as an experiment.

ssh server-a "docker run --rm -i postgres bash -c 'echo $(cat server-a-pgpass) > ~/.pgpass && chmod 0600 ~/.pgpass && pg_dump -h hostname -U username -d database -F c -b -v'" \
  | ssh server-b "docker run --rm -i postgres bash -c 'echo $(cat server-b-pgpass) > ~/.pgpass && chmod 0600 ~/.pgpass && pg_restore --verbose --clean --no-acl --no-owner -h hostname -U username -d database'"

So what’s going on here? Let’s break it down:

  • At a high level, we are piping server-a’s database straight into server-b’s.
  • We need to provide credentials to Postgres. We achieve this by injecting a .pgpass file into the container and assign the correct permissions.
  • We provide the --rm flag to docker run in order to remove the container after it exits. This way we don’t leave the credentials lying around.

Although this has come is very handy for me, it obviously has its limitations. With large amounts of data, I expect piping the data would become infeasible at some point. Luckily for me, the databases I’m working with are relatively small.