Docker Config, how to always use base image with Docker Swarm!

Docker Apr 16, 2018

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>

Conclusion

With Docker Configuration, you have a lot of base image that you can use without building and maintain a custom image like nginx, prometheus.

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!

Tags

Julien Maitrehenry

I specialize in DevOps, Agile practices and web development. I love sharing my knowledge for helping other people to go to the next level!

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.