Blitz is the German word for lightning and also a zero dependency, bi-directional, containerized source code synchronizer. It enables you to work around slow bind-mounts when using Docker for Mac. In other words, Blitz gives you lightning fast access to files on your Docker host from your containers.
Blitz uses the Unison File Synchronizer under the hood to synchronize files and folders between your local file-system and a Docker volume. Containers that need access to the files can simply mount the volume and read/write files with native speed.
Blitz expects the following mounts:
- Mount your source code via a bind mount to
/host
. Make sure to use thecached
option to speed up access to the files. - Mount a named volume to
/container
. Unison will synchronize/host
and/container
- in other words this volume will contain the source code. Make sure to use thenocopy
option to prevent existing files to be copied from your image to the volume. Otherwise you run into the risk of getting synchronization conflicts or lost files. - Add another volume that will hold the synchronization state to
/unison_data
Blitz supports two modes - run
and watch
.:
run
performs a one time synchronizations and should be used for the initial synchronizationwatch
will watch for filesystem changes and trigger a synchronization for every change
It is recommended to run an initial synchronization before running Blitz in /watch/ mode for the first time.
version: '3.7'
services:
blitz:
image: codetales/blitz:0.3.2
volumes:
# The bind mount to give blitz access to the local copy of your source code
- ./:/host:cached
# The volume that will hold
- code:/container:nocopy # The source code - other services should mount this volume for source code access.
# The unison synchronization state data
- unison:/unison_data
command: ["watch"] # Set the mode to `watch`
environment:
# Set additional unison flags
- UNISON_OPTS=-ignore "Path tmp"
# Define one or more services that will access the source code via the synchrtonized volume.
app:
image: myapp:development
build: .
volumes:
# The volume containing the src code
- code:/usr/src/app:nocopy
# Volume definitions
volumes:
code:
unison:
You can kick of the initial synchronization with
docker-compose run blitz run
Then start the service to keep synchronizing changes.
UNISON_OPTS
: Allows you to specify additional preferences for Unison. The default is none.SYNC_UID
: Use this environment variable to change the user id that is used to run Unison. You might want to set this to the same user id that you use to run your application inside the container. The default is user id 0 (root)MONIT_ENABLED
: Enable or disable monitoring the Unison process via Monit see Known issues. The default istrue
.MONIT_CHECK_INTERVAL
: Specifies the check interval for Monit in seconds. Default is1
.MONIT_HIGH_CPU_THRESHOLD
: Defines the threshold for the cpu usage of Unison in percentage. The default is60
MONIT_HIGH_CPU_CYCLES
: The number of cycles for which the cpu usage needs to be above the threshold before Monit will restart Unison.
It might make sense to keep the configuration of Blitz separate to not interfere or change the development experience on Linux and Windows machines.
Just place create a separate Docker Compose config for the Blitz service., volumes and bind mount for the application:
-
docker-compose.yaml
services: app: image: myapp:development build: . volumes: - ./:/usr/src/app
-
docker-compose.blitz.yaml
services: app: volumes: - code:/usr/src/app:nocopy # We override the bind mount here and use the volume instead blitz: image: codetales/blitz:0.3.2 volumes: - ./:/host:cached - code:/container:nocopy - unison_data:/unison_data volumes: code: unison_data:
You can then reference this file when starting Docker Compose either
- via the command line:
docker-compose -f docker-compose.yaml -f docker-compose.blitz.yaml up -d
- by setting the
COMPOSE_FILE
environment variableCOMPOSE_FILE=docker-compose.yaml:docker-compose.blitz.yaml
I usually set COMPOSE_FILE
in my .env
file. Docker Compose will automatically pick it up and you can just run
docker-compose up -d
You can synchronize multiple directories by adding multiple services for Blitz. Make sure to assign different volumes for the source code and unison data to each service.
Under certain circumstances, the Unison process might stop working and consume almost 100% of a CPU. This seems to happen when a lot of file system changes happen in a very short time - for example when switching between git branches.
To work around this issue, Blitz uses Monit. Monit will watch the Unison process and restart it if the CPU load is above a certain threshold for long enough. The default is 5 seconds. You can use the MONIT_ENABLED
, MONIT_HIGH_CPU_THRESHOLD
, and MONIT_HIGH_CPU_CYCLES
environment variables to change this behavior.
Check out docker-sync by EugenMayer or Crane if you are looking for an alternative to Blitz
Fork https://github.com/codetales/blitz, do your work and create a PR.
- Add an option to set the
prefer
option for unison to decide whether the host or container should win in case of conflicts - Specify files and directories to exclude via environment variables
- Add an option to automatically exclude version control files
- Validate settings on startup
Testing is currently done via a shell script. Run it via
./test.sh
The script ensures that files are correctly synchronized between the Docker Host and the Docker Volume.
I decided to go with a shell script here because
- Blitz has to be tested from the Docker Host and I didn’t want to introduce a lot of dependencies
- Speed and timing the file synchronization between the Host and Volume is depending on the Docker Host. This means that the test suite might be brittle and hence not worth spending too much effort into it
- I wanted something that is easy to debug and understand. The script just executes shell commands and dumps all commands and their output onto the terminal.