Copy Files to and from a Container

Problem: I needed to copy some database files into a container running on Kubernetes without modifying the image or restarting the parent Pod.

Solution: The Kubernetes CLI includes a sub-command for copying files into and out of a running container: kubectl cp /tmp/foo <some-pod>:/tmp/bar

Background

I’ve never found the need to copy files into a running container without issuing an updated image. This is somewhat of an anti-pattern as modifications to containerised filesystems that aren’t mounted externally are lost when the container process terminates.

I was trying to seed the Trivy vulnerability database in an air-gapped deployment (instructions here).

The Kubernetes documentation is the best place to go for a full description of how to use kubectl cp. Options are limited but there are examples for most use-cases.

The diagram is in two halves; local and cluster. In the local half it shows a file and the kubectl cli. In the cluster half it shows tar running in a pod and the file persisted to the underlying host filesystem.

Diagram showing my understanding of how the copy command works.

The documentation includes the following note:

“!!!Important Note!!! # Requires that the ’tar’ binary is present in your container # image. If ’tar’ is not present, ‘kubectl cp’ will fail.”

This piqued my curiosity. Why the need for the tar command? How do you copy a file into a container? A look at the source code shows the following:

  1. Start a go routine to tar the source and write it to an io.Writer
  2. Run tar -xmf - inside the target container using kubectl exec
  3. Connect the io.Writer from #1 to stdin on #2

The command run in the container extracts the tar stream. The -f - option tells us it reads the stream from stdin.

If I’d had to guess how this was implemented, I’d have assumed the command was somehow copying files directly to the container filesystem on the underlying node. The actual solution is a lot nicer.