For one file, the simplest pattern is to stream the file into the container and redirect it to a destination path.
1LOCAL_FILE="./config.yaml"
2NAMESPACE="default"
3POD="my-app-7f9b6d4c9b-abcde"
4CONTAINER="app"
5DEST_FILE="/app/config/config.yaml"
6
7cat "$LOCAL_FILE" \
8| kubectl exec -i -n "$NAMESPACE" "$POD" -c "$CONTAINER" -- sh -c "cat > $DEST_FILE" kubectl exec -n "$NAMESPACE" "$POD" -c "$CONTAINER" -- ls -lah "$DEST_FILE" ``` This works well when the container has a shell and `cat`, which is common even in fairly small images. ## Directory Copy With `tar` For directories or more complex file sets, `tar` streaming is usually better. ```bash LOCAL_DIR="./assets" NAMESPACE="default" POD="my-app-7f9b6d4c9b-abcde" CONTAINER="app" DEST_DIR="/app" tar -C "$LOCAL_DIR" -cf - . \ | kubectl exec -i -n "$NAMESPACE" "$POD" -c "$CONTAINER" -- tar -C "$DEST_DIR" -xf - ``` This preserves nested structure naturally and avoids manually copying files one by one. The main requirement is that `tar` must exist both locally and inside the container. ## Minimal-Tool Containers Some very small images do not include `tar`. In that case, you can still move small files with base64 if the container has the matching tools. ```bash LOCAL_FILE="./settings.json" DEST_FILE="/tmp/settings.json" base64 "$LOCAL_FILE" \ | kubectl exec -i -n "$NAMESPACE" "$POD" -c "$CONTAINER" -- sh -c "base64 -d > $DEST_FILE" ``` This is fine for small files, but it is not the first choice for larger transfers because it adds overhead and depends on `base64` being present in the container. ## Pick the Correct Pod and Container In multi-container pods, always specify the target container with `-c`. Also remember that pod names are ephemeral, so scripts often resolve pods by label rather than hardcoding the current name. ```bash NAMESPACE="default" APP_LABEL="app=my-app" CONTAINER="app" POD=$(kubectl get pod -n "$NAMESPACE" -l "$APP_LABEL" -o jsonpath='{.items[0].metadata.name}') echo "$POD" ``` That reduces mistakes during rollouts and restarts. ## Treat the Pod Filesystem as Ephemeral Copying a file into a running container usually changes only that pod instance. If the pod restarts, the file is often lost unless it was written to a persistent volume. This matters operationally. Ad hoc file injection is fine for debugging, incident response, or temporary config changes, but it is not a substitute for rebuilding the image or using proper configuration management when the change should persist. ## Common Pitfalls A common mistake is writing to a path that is read-only in the container filesystem. Many hardened images do not allow arbitrary writes everywhere. Another issue is forgetting the container name in multi-container pods. The command succeeds, but the file lands in the wrong container. Developers also sometimes assume the copied file will survive pod restarts. Unless the destination is backed by a persistent volume, that assumption is usually wrong. Finally, always verify the transfer. A successful shell pipeline does not guarantee the application can actually read or use the resulting file. ## Summary - '`kubectl exec` can replace `kubectl cp` by streaming file contents into the container.' - Use `cat` redirection for single files and `tar` streaming for directories. - Choose a method that matches the tools available inside the container. - Target the correct pod and container, ideally by label rather than hardcoded pod name. - Remember that copied files are usually ephemeral unless written to persistent storage.