Shinyproxy: Passing SQL credentials at runtime with the shinyproxy application.yml

Created on 27 Oct 2020  ·  5Comments  ·  Source: openanalytics/shinyproxy

Hi,

I have a working shinyproxy app with ldap authentication. However, for retrieving data from the SQL-database i now use (not recommended) a hardcoded connectionstring in my R code with the credentials mentioned herein (i use a service user because my end users don't have permissions to query the database):

con <- DBI::dbConnect(odbc::odbc(), encoding = "latin1", .connection_string = 'Driver={Driver};Server=Server;Database=dbb;UID=UID;PWD=PWD') 

I tried to replace this connection string with an environmental variable, that i pass from my linux host to the container. The R code now changed to:

connString <- Sys.getenv("CONNSTRING")
connString <- sub("\\\\","\\", connString)
con <- DBI::dbConnect(odbc::odbc(), encoding = "latin1", .connection_string = connString)

This works fine when running the container outside ShinyProxy, and thus by passing the environmental variables at runtime with the following docker command:

docker run -it --env-file .env.list app123 

The environmental variable is also found when entering the running container and typing 'env'.

However, when using ShinyProxy, it is not clear to me how to configure this in the yaml config file and in the bash-command at runtime. How do i define the parameter container-env-file for the app container? And how do i pass the statement --env-file .env.list at runtime so that it is picked up in the linked containers?

My application yaml looks now like this (i intentionally left the ldap config blank):

proxy:
  port: 8080
  authentication: ldap
  admin-groups: admins
  ldap:
    url: url
    manager-dn: manager-dn
    manager-password: manager-password
    user-search-base: user-search-base
    user-search-filter: user-search-filter
    group-search-filter:  group-search-filter
    group-search-base: group-search-base  
  docker:
      internal-networking: true
  specs:
  - id: 01_ok
    display-name: dashboard
    description: Dashboard 
    container-cmd: ["R", "-e", "shiny::runApp('/root/R')"]
    container-image: hberten/app123
    container-env-file: .env.list
    container-network: shineyproxyn-net
    access-groups: [GG_APP_ShinyProxy]

logging:
  file:
    shinyproxy.log

I then run the following command to start the ShinyProxy container:

sudo docker run -d --env-file ~/.env.list -v /var/run/docker.sock:/var/run/docker.sock --net shineyproxyn-net -p 8080:8080 hberten/shinyproxy

A related issue is found here, but this one uses a Docker compose.yml. Is it possible to configure things without a Docker Compose? What am i missing?

Any help kindly appreciated!

question

Most helpful comment

I will try to explain more clearly: you have a host system and 2 containers: one outer where shinyproxy is running and one inner with your app.
By running docker run --env-file ... on your host system, you make environment variables from that file on the host system available to the outer container as env vars. Now you can pass them further to the inner container using container-env variable.
Alternatively you can mount the host folder with your file into your outer container, and then you can make the env vars from that file available in your inner container by using container-env-file variable.

An example command for the 2nd alternative may be somehting like:

sudo docker run -d -v /home/envs:/tmp/envs -v /var/run/docker.sock:/var/run/docker.sock --net shineyproxyn-net -p 8080:8080 hberten/shinyproxy

assuming your .env.list file is located in /home/envs/ on your host - you make it available in the outer container under /tmp/envs/env.list with volume mount - now you can use container-env-file: /tmp/envs/.env.list in your application.yml

An example for the 1st alternative is to use your original command, and then in the application.yaml use container-env with something like:

container-env:
  VAR11: "${VAR1}"
  VAR22: "${VAR2}"

where VAR1 and VAR2 are env vars defined in the file on the host and hence available as env vars in outer container, and here you pass them to the inner container as VAR11 and VAR22 (for example, you can of course use the same names too)

All 5 comments

Hi @Bertusian,
I think the problem is that you are running shinyproxy itself in a container, so you need to make your .env.list file available inside that container (by volume mounting it), or alternatively use container-env with env vars that you pass via file in your docker run command. In addition, I believe that container-env-file expects an absolute path.

Hi @ mnazarov.

Indeed, i am running shinyproxy in a container. Can you eventually provide an example of the runtime command for lauching the shinyproxy container (with .env.list volume mounted), and is it then captured by the R-app container? I thought that the .env.list was made available by adding --env-file ~/.env.list (that worked when running the container without shinyproxy).
And do i still need to adapt the application.yml? Still not very clear to me. Grateful for any assitance or an example...

I will try to explain more clearly: you have a host system and 2 containers: one outer where shinyproxy is running and one inner with your app.
By running docker run --env-file ... on your host system, you make environment variables from that file on the host system available to the outer container as env vars. Now you can pass them further to the inner container using container-env variable.
Alternatively you can mount the host folder with your file into your outer container, and then you can make the env vars from that file available in your inner container by using container-env-file variable.

An example command for the 2nd alternative may be somehting like:

sudo docker run -d -v /home/envs:/tmp/envs -v /var/run/docker.sock:/var/run/docker.sock --net shineyproxyn-net -p 8080:8080 hberten/shinyproxy

assuming your .env.list file is located in /home/envs/ on your host - you make it available in the outer container under /tmp/envs/env.list with volume mount - now you can use container-env-file: /tmp/envs/.env.list in your application.yml

An example for the 1st alternative is to use your original command, and then in the application.yaml use container-env with something like:

container-env:
  VAR11: "${VAR1}"
  VAR22: "${VAR2}"

where VAR1 and VAR2 are env vars defined in the file on the host and hence available as env vars in outer container, and here you pass them to the inner container as VAR11 and VAR22 (for example, you can of course use the same names too)

OMG. This is great! Now it works. I haven't tried the first suggestion (but will do later), but your second solution did it straight way! I knew i was close, but couldn't find it.

Thank you very much!!

Great stuff you folks are doing with ShinyProxy.

I am glad it worked!

Was this page helpful?
0 / 5 - 0 ratings