I am trying to implement the CI/CD pipeline for my project using Docker, Kubernetes and Jenkins. My application is multi-tenant application in which database application variables everything is different for different tenant.
Application Strategy
When I am building a docker image I am using a Dockerfile. And I keep my Dockerfile inside my SVN code repository. For every tenant, code repository is same. When I am building an image, at that time I need to build different images for different tenant.
Dockerfile implementation
In my docker file I am adding entry point like the following,
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=tenant1config" , "TestProject.war"]
If I need to build Docker image for another tenant , need to add-Dspring.profiles.active=tenant2config
So the entrypoint in the Dockerfile is dynamic.
My Confusion
How can I find a good standard way of implementation of this problem?
Quoting from 12 Factor - Config
An app’s config is everything that is likely to vary between deploys (staging, production, developer environments, etc). This includes:
Resource handles to the database, Memcached, and other backing services
Credentials to external services such as Amazon S3 or Twitter
Per-deploy values such as the canonical hostname for the deploy
You should not build separate docker images for each tenant as the binary should be the same and any runtime configurations should be injected through the environment.
There are different options to inject runtime configuration
Instead of hardcoding the profile in the entrypoint add a environment variable
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=$TENANT_PROFILE" , "TestProject.war"]
Then inject the environment variable from the kubernetes deployment configuration Refer https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/
Your entrypoint will look like
ENTRYPOINT ["java", "-jar", --spring.config.location="file:/path/to/tenantconfig.yaml" , "TestProject.war"]
Then mount the required config file as a kubernetes config.
Either way externalize the runtime configuration from the docker image and inject it through the deployment configuration as a environment variable or a config.
You can make use of docker ARGS, this will only be available at build time and this can used at entrypoint.
docker build --build-arg CONFIG_FILE=<file_name> -t tag_name .
CONFIG_FILE will hold the location of config file and you can pass it dynamically. Replace your entry point with $CONFIG_FILE
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=$CONFIG_FILE" , "TestProject.war"]
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