5

I am trying to run my app in websphere liberty profile container. I want to have 1 image which can be run on diff env(dev, st, sit etc). I can use env variable to pass the values at runtime to the container. How to use those in wlp settings? Is this possible?

In the server.xml, I have defined the datasource with all config properties like connection string, username and password. I have built the image using this file. Now, I want to test the same image in different env by passing the values as env variable instead of hardcoding in the server.xml. I couldn't find a way where server.xml can read the env var directly and replace the password variable. Other way I tried is using the bootstrap.properties and so server.xml can read the values from that file. But here also, I have to provide the bootstrap.properties during image building and I can't change the values during runtime.

lines in server.xml:

<dataSource name="XYZ" jndiName="jdbc/xyz" transactional="false"> <jdbcDriver id="OracleJdbcDriver" libraryRef="xyzLib"/> <properties.oracle URL="${db.url}" user="${db.username}" password="${db.password}"/> </dataSource>

db.url, db.username and db.password are defined in bootstrap.properties which is packaged in the image during build time.

Lata
  • 53
  • 3

2 Answers2

5

From this:

The following predefined variables can be referenced:
* directory properties, see Liberty: Directory locations and properties
* JVM system properties
* process environment variables

If the same variable is specified in multiple places, the precedence is as follows:
* variables in bootstrap.properties override the process environment variables
* variables in server.xml, or included XML files, override the variables in bootstrap.properties and process environment variables

Use process environment variables in the configuration. Process environment variables are available if you use the env. configuration variable prefix, for example:

<fileset dir="${env.LIBRARY_DIR}" includes="*.jar"/>

For more information on specifying environment variables, see Customizing the Liberty environment.

Then, a probable solution is:

server.xml:

<properties.oracle URL="${env.db_url}" user="${env.db_username}" password="${env.db_password}"/>

Pass environment to container just when run it:

docker run -d -e db_url=xxx -e db_username=xx -e db_password=x your_image

Then, different values will be passed to different containers & finally referenced by server.xml with env. format.

UPDATE:

From @Lata 's try as next:

I tried the scenario with capital and small letters. What I got is it doesn't matter which casing you use in server.xml. But while calling the docker run, you have to pass the variables in CAPS only to work.

  • server.xml - CAPS Letter
    • docker run - CAPS letter - works
    • docker run- smallcase letter - doesn't work.
  • server.xml - smallcase letter
    • docker run -CAPS letter - works.
    • docker run - smallcase letter - doesn't work.

So, the final conclusion should be: no matter CAPS or LOW case letter in server.xml, but need to pass CAPS env to docker run. As docker not have such limits, so definitely websphere enforce this limit.

atline
  • 28,355
  • 16
  • 77
  • 113
  • Thanks Atline. This solution, I have already tried before to start with. Here is what I get: In the container, I can see the correct env variable values that I pass with -e flag during docker run command. But, when my application runs, it throws error saying incorrect port and password supplied to datasource. So, it seems the values are not getting passed on to server.xml. Are you sure that this will work out or have tried before. I can try debugging, to see if there is any other issue the way I am trying then. – Lata Jul 03 '19 at 06:55
  • To be honestly, I'm not very sure, but from doc, it seems work. Another definite workable way I think is to have a `docker_entrypoint.sh` for yourself to override the default entrypoint, in which you can write the `environment variable` in container to `server.xml` & finally in this script to start your web server. – atline Jul 03 '19 at 07:42
  • 2
    This works, but make sure you use upper case variables, like `env.DB_URL`, not `env.db_url` in both places, and not use dots like `db.password`, but `DB_PASSWORD` – Gas Jul 03 '19 at 08:06
  • Interesting, Lata, you may try CAPITAL suggest by @Gas, if it works, I will update the answer. And seems the example from doc all CAPITAL letter... – atline Jul 03 '19 at 08:10
  • 2
    It definitely works; I'm using it for my Docker Liberty images. I'm using capitalized environment variables as well, having followed the examples without thinking about that detail, and just being used to environment variables being capitalized. But I don't think I would have expected capitalization to have mattered. – dbreaux Jul 03 '19 at 13:49
  • Thanks All. It finally worked with env variables for me. The problem was with the passowrd having special char and I forgot to put it in quotes. – Lata Jul 04 '19 at 06:05
  • glad you find the key. – atline Jul 04 '19 at 06:06
  • @atline @Gas @dbreaux. It worked with below: while calling docker run. `` `docker run -d -e DB_URL=urlvalue -e DB_USERNAME=unamevalue -e DB_PASSWORD='passvalue'` – Lata Jul 04 '19 at 06:11
  • @Lata So you confirm we need to use CAPITAL letter? – atline Jul 04 '19 at 06:12
  • @atline I havent tried passing smallcase letters. So, directly tried with caps letter at both places- server.xml and docker run command. Once I will get some time, I will try that later and will udpate here. – Lata Jul 04 '19 at 07:54
  • @atline, I tried the scenario with capital and small letters. What I got is it doesn't matter which casing you use in server.xml. But while calling the docker run, you have to pass the variables in CAPS only to work. `"server.xml - CAPS Letter, docker run - CAPS letter - works and docker run- smallcase letter - doesnt work. " "server.xml - smallcase letter docker run -CAPS letter works. docker run - smallcase letter doesnt work."` – Lata Jul 05 '19 at 06:43
  • @Lata That's great, I have updated your effort to answers to benefit later guys, also would you please accept this answer like guide in https://stackoverflow.com/tour ? – atline Jul 05 '19 at 06:54
3

While the response from @atline is correct for older releases of Liberty since the question is running in Docker containers they are very likely running on a version of Liberty since 19.0.0.3 which has different behaviour regarding variable resolution.

Since 19.0.0.3 environment variable resolution has not required the env. prefix and doesn't require the variable name to be in upper case. As documented at this link

Environment variables can be accessed as variables. From 19.0.0.3, they can be accessed directly by referencing the environment variable name. If the variable cannot be resolved the following transformations on the environment variable name is tried:

  • Replace all non-alpha num characters with _
  • Change all characters to upper case.

If you enter ${my.env.var} in server.xml it will look for environment variables with the following names:

  • my.env.var
  • my_env_var
  • MY_ENV_VAR

When using a Liberty release older than 19.0.0.3, environment variables can be accessed by adding env. to the start of the environment variable name:

<httpEndpoint id="defaultHttpEndpoint"
             host="${env.HOST}"
             httpPort="9080" />

Based on the question it seems that the value is being specified in bootstrap.properties as well as in environment variables and bootstrap.properties overrides environment variables:

You can parameterize server config using variables. When resolving variable names the following sources are consulted in increasing order of precedence:

  • server.xml default variable values
  • environment variables
  • bootstrap.properties
  • Java system properties
  • server.xml config

To get them read from docker you need to remove them from bootstrap.properties. Given your example:

<dataSource name="XYZ" jndiName="jdbc/xyz" transactional="false">
    <jdbcDriver id="OracleJdbcDriver" libraryRef="xyzLib"/>
    <properties.oracle URL="${db.url}" user="${db.username}" password="${db.password}"/>
</dataSource>

if you remove the definition of db.url, db.password and db.username from bootstrap.properties then you can start a docker image thus:

docker run -d -e db_url=xxx -e db_username=xx -e db_password=x your_image

If you want to have defaults defined in case those are not specified then you can add this to your server.xml:

<variable name="db.url" defaultValue="jdbc:XXX"/>
<variable name="db.username" defaultValue="testUser"/>
<variable name="db.password" defaultValue="testPassword that will be encoded or encrypted"/>

If you want to encode or encrypt the password so it isn't in plain text you can use:

securityUtility encode --encoding=[xor|aes]

the full help for all the options is available by running:

securityUtility help encode
Community
  • 1
  • 1
Alasdair
  • 3,071
  • 15
  • 20
  • Thanks @Alasdair. It worked for me with env variable. We are still using version 19.0.0.2 , so I had to use env. prefix. – Lata Jul 04 '19 at 06:06