Hot container replacement with Docker

We all love Docker, it makes deployment a lot easier. However, when it comes to test small changes, it can be cumbersome to rebuild and rerun the containers manually. Luckily Docker already addressed this issue for us.

Prerequisites

  • Installed Docker Compose version 2.22.0 or greater

If you already have Docker on your machine, please verify it's version:

docker compose version

Otherwise follow the official installation instructions.

Getting started

For hot container replacement, we have to modify the project's compose.yml (or docker-compose.yml). Apply the following syntax to the container you want to update frequently:

<your-custom-service>:
  image: <your-custom-image-name>
  build: <relative-path-to-your-service>
  # hot container replacement
  develop:
    watch:
    - path: <relative-path-to-your-service>
      action: <your-action>

And run the project in develop mode:

docker compose watch
💡
Note that it comes with some limitations

As it can be seen, the develop attribute does the magic, but let me explain it's parts. It has a watch attribute taking a list of attributes. For each sub attribute, we have to define the path and the action. The idea is what should happen when a file changed under the path.

Docker Compose comes with the following actions:

  • rebuild - stops the service, triggers it's build attribute and restarts it with the newly created image.
  • sync - it keeps the service running, but copies the changed files into the container. Hence the container's file system usually differs from the host machine's, we must provide a target attribute as well. target is the destination path of the changed files.
  • sync+restart - like sync, but it restarts the container. Note that it's available with Docker Compose version 2.23.0 and later

Wait for a second! What if there are files under path, but we don't want the action executed in their case? If the build directory contains .dockerignore, then that files are already excluded.

Alternatively, one can use the ignore attribute. It takes a list of .dockerignore like patterns. Like bellow:

develop:
    watch:
    - path: <relative-path-to-your-service>
      action: <your-action>
      ignore: 
      - <your-files-to-be-ignored>
💡
You can check if your compose.yml is correct with a tool like YAMLlint

Use case examples

sync action

You can watch an example here.

sync+restart action

You can read about it here.

rebuild action

You can read about it here.

Limitations

When you run Docker in develop mode, there is no detached mode. If you want to use the terminal further, you have to open another terminal session.

Furthermore when you terminate the process, Docker keeps running the services. So make sure you run docker compose down after you done.

Known issues

If one uses Docker on a virtual machine or on WSL, while developing on host machine, his changes won't get detected. He must work directly on the VM or Docker has to be installed locally.

References

Thank you for reading! Keep coding!