Managing Dockerfile dynamically for different tenants in CI/CD pipeline implementation
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
- 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/
- 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.
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"]