Remember last time you say "It's a really awesome image ٩(◕‿◕｡)۶ ! But I need only to change one thing in the configuration, and I make a new image, a new git repository, a build process, and push my new image to a registry (╥_╥)"
Now (ok, a few months ago), it's possible with Docker Swarm to just add a configuration to your image!
Let's try it with Prometheus, a monitoring system and time series database.
Prometheus scrape an endpoint and store the metric in the internal time series database. But, when you add a new service, you need to change the Prometheus configuration for adding it. Who says changing a configuration, says recreating an image.
But, no more!
This is the basic docker-compose file that we will change for adding the new configuration without changing the base image:
# prometheus.yml version: "3.4" services: prometheus: image: prom/prometheus:v2.2.0 networks: - monitoring command: - '--config.file=/etc/prometheus/prometheus.yml' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--storage.tsdb.path=/prometheus' - '--storage.tsdb.retention=24h'
Note: Docker configs are only available to swarm services, not to standalone containers. To use this feature, consider adapting your container to run as a service with a scale of 1.
Adding a configuration to your container
For adding a configuration to Docker, we can create it by hand with
docker config create <config name> <file name or stdin> and use the configuration name in our docker-compose file or we can manage it directly inside the docker-compose file:
version: "3.4" configs: <config name>: file: <file name> external: true|false # If the configuration was created outside this docker-compose # file, we need to set it to true services: <service name>: configs: - source: <config name from before> target: <path inside the container where the configuration will be mounted>
Now, if we update our previous stack:
# prometheus.yml version: "3.4" configs: prometheus_config: file: ./prometheus.yml services: prometheus: [...] configs: - source: prometheus_config target: /etc/prometheus/prometheus.yml
Rotate a configuration
Keep in mind that configurations are immutable, so you can’t change the file for an existing service. Instead, you create a new configuration to use.
Why? Because with an immutable configuration, you can be sure that all your containers inside a service always have the same configuration, and this gives you the opportunity to change it everywhere at once.
To rotate a service, you need to:
- create a new configuration with a different name
- update the service by removing the old config
- add the new one to your service and use the same mount point
You can do this by using the cli:
$ docker service update \ --config-rm prometheus_config \ --config-add source=prometheus_config_v2,target=/etc/prometheus/prometheus.yml \ <stack-name>_prometheus
Or by updating the compose file and by redeploying the stack:
# prometheus.yml version: "3.4" configs: - prometheus_config: + prometheus_config_v2: file: ./prometheus.yml services: prometheus: [...] configs: - - source: prometheus_config + - source: prometheus_config_v2 target: /etc/prometheus/prometheus.yml
$ docker stack deploy -c prometheus.yml <stack-name>
With Docker Configuration, you have a lot of base image that you can use without building and maintain a custom image like
If you want to learn more about Docker configuration, you have a complete guide available within the docker documentation: Store configuration data using Docker Configs
If you find a typo, have a problem when trying what you see in this article, please contact me!