I'm working on a service in a 'system' orchestrated using docker-compose. The service is written in a compiled language and I need to rebuild it when I make a change. I'm trying to find the best way to quickly iterate on changes.
I've tried 2 'workflows', both rely on being linked to the source directory via a volume:
to get the latest source.
docker-compose up -d
docker-compose run --name SERVICE --rm SERVICE /bin/bash
CMD
to build and then run the service)docker-compose kill SERVICE
docker-compose up -d --no-deps SERVICE
The problem is both take too long to restart vs restarting the service locally (running on my laptop independently of docker). This setup seems to be ok with interpreted languages that can hot-reload changed files but I've yet to find a suitably fast system for compiled language services.
Step 1: Define the application dependencies. Step 2: Create a Dockerfile. Step 3: Define services in a Compose file.
The docker compose up command aggregates the output of each container (like docker compose logs --follow does). When the command exits, all containers are stopped. Running docker compose up --detach starts the containers in the background and leaves them running.
Introduction to Docker ComposeYou can use Docker Compose to define your local development environment, including environment variables, ports you need accessible, and volumes to mount. Everything is defined in docker-compose. yml , which is used by the docker-compose CLI. The first section defines the web service.
yml when building a multi-container Docker application. The docker-compose. yml file lets you define a set of related services to be deployed as a composed application with deployment commands. It also configures its dependency relations and runtime configuration.
I would do this:
Run docker-compose up
but:
entrypoint
that does something likeentrypoint.sh:
trap "pkill -f the_binary_name" SIGHUP
trap "exit" SIGTERM
while [[ 1 ]]; do
./the_binary_name;
done
Write a script to rebuild the binary, and copy it into the volume used by the service in docker-compose.yml
:
# Run a container to compile and build the binary
docker run -ti -v $SOURCE:/path -v $DEST:/target some_image build_the_binary
# copy it to the host volume directory
copy $DEST/... /volume/shared/with/running/container
# signal the container
docker kill -s SIGHUP container_name
So to compile the binary you use this script, which mounts the source and a destination directory as volumes. You could skip the copy step if the $DEST
is the same as the volume directory shared with the "run" container. Finally the script will signal the running container to have it kill the old process (which was running the old binary) and start the new one.
If the shared volume is making compiling in a container too slow, you could also run the compile on the host and just do the copy and signaling to have it run in a container.
This solution has the added benefit that your "runtime" image doesn't need all the dev dependencies. It could be a very lean image with just a bare OS base.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With