Search code examples
dockerdocker-composeconsul

How can i set my container parameters from consul values through docker?


I have few simple java applications and i want them to use consul for runtime configuration. I can't understand the approach that should be used at this combo: docker + consul + apps.

I've managed to customize a proper docker-compose.yml file with required containers: consul, jetty1, jetty2, jetty3. Each jetty gets a war application on build. When i docker-compose up my stack i have a proper applications started. But i can't understand what should i do to make my apps read consul config from the consul service.

I've made such docker-compose.yml file:

version: '2'

services:
  consuldns:
    build: ./consul
    command: 'agent -server -bootstrap-expect=1 -ui -client=0.0.0.0 -node=consuldns -log-level=debug'
    ports:
      - '8300:8300'
      - '8301:8301'
      - '8302:8302'
      - '8400:8400'
      - '8500:8500'
      - '8600:53/udp'
    container_name: 'consuldns' 
  jettyok1:    
    build: ./jetty
    ports:
      - "8081:8080"     
    container_name: jettyok1  
    depends_on: 
      - consuldns
  jettyok2:    
    build: ./jetty
    ports:
      - "8082:8080"     
    container_name: jettyok2    
    depends_on: 
      - consuldns
  jettyok3:    
    build: ./jetty
    ports:
      - "8083:8080"     
    container_name: jettyok3
    depends_on: 
      - consuldns

i have two folders near docker-compose.yml file: - consul: Dockerfile (copied from official repo)

FROM consul:latest

ENV CONSUL_TEMPLATE_VERSION 0.18.1

ADD https://releases.hashicorp.com/consul-template/${CONSUL_TEMPLATE_VERSION}/consul-template_${CONSUL_TEMPLATE_VERSION}_linux_amd64.zip /

RUN unzip consul-template_${CONSUL_TEMPLATE_VERSION}_linux_amd64.zip && \
    mv consul-template /usr/local/bin/consul-template &&\
    rm -rf /consul-template_${CONSUL_TEMPLATE_VERSION}_linux_amd64.zip && \
    mkdir -p /etc/consul-template/config.d/templates && \
    apk add --no-cache curl

RUN apk update && apk add --no-cache jq

RUN mkdir /etc/consul.d
RUN echo '{"service": {"name": "my_java_application", "tags": ["java"], "port": 8080}}' > /etc/consul.d/java.json
#RUN consul agent -data-dir /consul/data -config-dir /etc/consul.d

CMD ["agent", "-dev", "-client", "0.0.0.0"]
  • jetty: Dockerfile (handmade)
FROM jetty:latest

ENV DEFAULT_SYSTEM_MESSAGE='dockerfile default message'

COPY \always-healthy.war /var/lib/jetty/webapps/

always-healthy.war is a simple spring-boot web app with a single GET method support:

package org.bajiepka.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.core.env.Environment;

@RestController
public class MessageController {

    @Autowired
    private Environment environment;

    @GetMapping("/message")
    public String getDefaultMessage(){
        return String.format("Current value: %s", environment.getProperty("DEFAULT_SYSTEM_MESSAGE"));
    }
}

Point me please, what should i do, to make my always-healthy apps read a value from consul service so i could manage an env parameter DEFAULT_SYSTEM_MESSAGE of any jetty instance or always-healthy application


Solution

  • If you are using Spring cloud you could use Spring cloud consul config to enable the app to load the configuration from consul at the startup.

    See samples and example here and here

    If you are not using spring cloud then it is a bit more work where you have to fetch the configuration using a rest client from consul.