Bi-directional file synchronization for containers in Kubernetes is now stable in DevSpace v4.1
kubectl cp is a very useful command but its capabilities are limited:
- it is uni-directional / 1-way (only upload or download)
- it is a one-time operation, i.e. it copies files once and then terminates (no continuous monitoring for file changes possible)
- it is quite slow because it first creates a
tararchive, then sends it and finally unpacks it on the other side (no batches, no parallelization)
So, what if you need more than a simple file copy using
DevSpace is an open-source dev tool for Kubernetes and includes a high-performance on-demand file sync which is now considered stable. It is like a
kubectl cp on steroids:
devspace dev starts a bi-directional file synchronization between the local working directory and a container's
Download DevSpace and test the sync command yourself. It works with any Kubernetes cluster and does not require any configuration. Just download the DevSpace binary and run the command. That's it.
Need more options?
devspace sync command provides the following flags:
- --no-watch to disable file watching (= stop after initial sync)
- --container-path to sync a specific container path (default:
- --local-path to sync a specific local path (default:
./= current dir)
- --exclude to exclude files and folders from sync (
- --pod & -l / --label-selector & --namespace to choose a pod without showing a dropdown selector
- --container to choose a container without showing a dropdown selector
How does it work?
In a nutshell,
devspace sync does the following:
- Inject a tiny sync binary into the container and establish a real-time connection between the local
devspace syncprocess and the binary running inside the container.
- Perform the initial sync of the files between the container and the filesystem on your local machine.
- Start a file-watcher on both sides to monitor files and sync them right when they are being changed.
If you need more than just file sync (e.g. log streaming, a terminal session or port-forwarding), take a look at the
0. Select Pod & Container
Running this command will show you an output similar to this one:
[info] Using kube context 'docker-desktop' [info] Using namespace 'blog-local' ? Select a pod [Use arrows to move, space to select, type to filter] > blog-7876b6fcd6-nzvs6 database-2123098109-jsk2la tiller-deploy-55956c5789-cxzs8
If you only have a single pod, DevSpace will skip this question and just use the pod. To skip the question, you can also specify the
If the pod you choose has multiple containers, DevSpace will also ask you to select which container you want to establish the file sync connection to. To skip this question, you can provide the
1. Inject Sync Binary
This step is the reason why DevSpace is so much faster and more reliable than any other file sync command, including
kubectl cp. Most other tools have the issue that:
- they transfer each file individually which is very slow or
- they archive all files, then transfer them, then unpack them which takes very long until you see any changes or
- they are unable to watch for changes inside the container or do this via polling (i.e. run
ls -l && statover and over again) or
- they only support certain types of storage (e.g. only multi-read-write persistent volumes) or
- they require certain libraries to be installed inside the container or
- they start side-car containers
By injecting a binary directly into the running container, DevSpace ships everything needed for a reliable and super fast bi-directional code synchronization. This allows DevSpace to:
- track file changes in real-time (faster and more reliable than polling)
- establish a stream connection which means that the receiving end already unpacks and processes changes without having to wait for all changes (e.g. archive with updated files) to arrive first
- make smart decisions about bundling and archiving many small files and transferring larger files separately
- overcome minor connectivity issues through reliable retry attempts
devspace dev works out of the box with any Docker container running inside a Kubernetes cluster. The only requirement is that the
tar command is available inside the container.
2. Initial Sync
The initial sync process runs a comparison of both filesystem trees before starting the real-time sync. This process makes sure that both filesystems are in sync before starting to listen to newly upcoming file changes. By default, the initial sync algorithm ensures that:
- all files which exist locally but not inside the container will be uploaded to the container
- all files which exist in the container but not on the local filesystem will be downloaded from the container
- all files which have different content inside the container than their counterparts on the local filesystem will be overwritten with the local files, i.e. local filesystem is the single source of truth and wins in case of conflicts
If you want to run
devspace sync as a one-time operation, you can provide the
--no-watch flag and DevSpace will terminate after completing the initial sync process.
3. Real-Time Sync
Unless you provide the
--no-watch flag, DevSpace will start the real-time sync after the initial sync is finished. Real-time sync means that DevSpace sets up file watchers on both sides (inside the container and on the local filesystem) and watches for all file changes. If a file change is detected on one side, DevSpace synchronizes the file to the other side.
When many files change at once or very quickly after each other, most file sync algorithms fail (e.g. with a fatal error) or miss important changes (e.g. due to buffer overflow). However, this is a very common scenario when you are programming. It happens for example when switching a branch with git or when installing dependencies. DevSpace reliably handles thousands of file changes which occur in parallel. If DevSpace detects that many files change in a short period of time, it does two things:
- DevSpace creates batches to efficiently group smaller files and transfer them together (bulk processing)
- DevSpace isolates very large files and synchronizes them in the background separately
- DevSpace starts a polling process in addition to the file watchers to make sure that no file change has slipped through due to the high volume of file watcher events
Stops the sync after completing the initial sync and does not start the file watchers. This is useful when you want
devspace sync to sync a folder once and terminate afterward. This is probably the closest to what
kubectl cp does with the differences that the sync algorithm works both ways instead of a 1-way copy of files.
Tells DevSpace which folder within the container to sync with the local path. By default, DevSpace is using the
WORKDIR defined within the Dockerfile.
Expects an absolute path starting with
Tells DevSpace which folder on the local filesystem to use for the sync. By default, DevSpace uses the current working directory from where the
devspace sync command has been started.
Can either be an absolute or a relative path.
Tells DevSpace which paths to exclude when running the sync algorithm. This flag expects the same path pattern syntax as
It is possible to provide
--exclude=[PATTERN]multiple times. Compared to a
--excludeflag would represent one line of the
-l / --label-selector &
These options can be used to select a specific pod. If DevSpace finds multiple pods, it shows a picker and asks the user to select a pod. If DevSpace only finds one pod, it just takes that one.
Tells DevSpace which container to use for the file sync, which is useful when the selected pod has multiple containers. If DevSpace finds multiple containers as part of the selected pod, it shows a picker and asks the user to select a container. If DevSpace only finds one container, it just takes that one.
Why do we care so much about this?
At DevSpace, we are building the
docker-compose for Kubernetes. With
docker-compose it is very easy to reflect file changes in running containers by mounting the project folder on the local filesystem directly into the container. With Kubernetes, this is not easily possible because Kubernetes clusters often do not run on the local development machine and even if they do (e.g. minikube or Docker Kubernetes), volume provisioning via persistent volume claims etc. does not allow to mount folders from your underlying host machine (at least not without a lot of extra effort).
devspace dev, the
docker-compose equivalent of DevSpace, uses the file sync algorithm to synchronize files between the local filesystem and the container, which allows you to code with your local IDE but still compile and test the code directly inside a container that can run in any Kubernetes cluster (local or remote).
devspace dev does a lot more than
devspace sync (e.g. port-forwarding, terminal proxy, log streaming) and there are also small differences in terms of the sync algorithm.
devspace sync vs
devspace dev uses essentially the same file sync procedures as
devspace sync, there is one important difference:
devspace syncdownloads all files which exist in the container but not on the local filesystem (at least by default)
devspace devdeletes all files which exist in the container but not on the local filesystem (at least by default)
This decision makes sense for
devspace dev because it is analogous to
docker-compose because Docker essentially mounts the local filesystem into the container, meaning that there are literally no differences between the container files and the local files.
devspace sync, however, it often makes sense to download the files which are existing in the container but not locally. Just think of the case where you simply want to download a log folder from the container to an empty directory on the local filesystem. Of course, you do not want to delete the log files but rather download them instead.
Tip: You can customize the behavior of both commands. If you want the
devspace synccommand to behave more like
devspace devand delete files which are not found locally, just provide the
Feedback or Questions?
If you have any feedback or questions regarding the file sync command or if you have any feature requests for an upcoming release, reach out to us via:
Get involved! Let us build the best developer tool for Kubernetes.