Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Managing Dockerfile dynamically for different tenants in CI/CD pipeline implementation

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

  1. For managing entry point command inside the Dockerfile is possible by dynamically?
  2. Or Do I need to add another Dockerfile for another tenant? And need to run the docker build command separately for separate tenant?

How can I find a good standard way of implementation of this problem?

like image 525
Mr.DevEng Avatar asked Oct 21 '19 09:10

Mr.DevEng


2 Answers

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

  1. Environment variables

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/

  1. Mount the profile configuration as a config and refer it

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.

like image 120
Mohit Mutha Avatar answered Nov 18 '22 21:11

Mohit Mutha


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"]
like image 3
Sivakumar Avatar answered Nov 18 '22 21:11

Sivakumar