This explains how the demo server (not running containers) was upgraded to v2.5.

This server runs multiple versions of Grouper at once.   v2.5 will run the UI/WS/Daemon/Scim in one container to save some memory.  This should not be done in production.

The demo server has an apache with a domain name and shib, so we will use the external apache (not in container), and point to TomEE inside the container.


Design decisions

  1. Will run tomcat only in container since Apache and Shib are already on host
  2. Will run the container as non-root for security reasons since it only has one process
  3. Sub-image with Dockerfile will be used so we can adjust the file ownerships in image
  4. The only mount needed is the logs directory


Lets see what version of docker we are running, make sure starts on boot

[root@i2midev6 ~]# docker -v
Docker version 19.03.8, build afacb8b

[root@i2midev6 ~]# sudo systemctl enable docker
Created symlink from /etc/systemd/system/ to /usr/lib/systemd/system/docker.service.
[root@i2midev6 ~]# /sbin/service docker start
Redirecting to /bin/systemctl start docker.service
[root@i2midev6 ~]# docker ps --all
[root@i2midev6 ~]# docker images list

Get Grouper container

  • See which version of Grouper to run
  • Pull the image

    [root@i2midev6 ~]#  docker pull i2incommon/grouper:2.5.XX

  • Make sure the digest is correct (from release notes page)

    [root@i2midev6 ~]# docker image inspect i2incommon/grouper:2.5.XX | grep i2incommon/grouper@sha256

  • Create a directory to mount files and folder in and out of container.  You might have one of these directories that is shared for ws/ui/daemon.

    [appadmin@i2midev6 container]$ mkdir -p /opt/grouper/2.5/container
    [appadmin@i2midev6 container]$ mkdir -p /opt/grouper/2.5/container/slashRoot/opt/grouper/grouperWebapp/WEB-INF/classes

Import configs to the database

See this wiki


We have a dockerfile so we can change the uid and gid of the user that runs tomcat, so it doesnt run as root

# this matches the version you decided on from release notes

FROM i2incommon/grouper:${GROUPER_VERSION}

# this will overlay all the files from /opt/grouper/2.5/container on to /
COPY slashRoot /

# [appadmin@i2midev6 bin]$ id
# uid=1870(appadmin) gid=100(users) groups=100(users),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

# Note, since the gid 100 is in container and not used: "users", it will be removed
# note  since the user "games" has primary gid of 100, need to get rid of that too.  And need to get rid of group games too for some reason

RUN groupdel games \
  && userdel games \
  && groupdel users \
  && /usr/local/bin/ tomcat 1870 \
  && /usr/local/bin/ tomcat 100 \
  && chown -R 1870:100 /opt/grouper \
  && chown -R 1870:100 /opt/tomee

Build sub-image command

[root@i2midev6 container]# more 

docker build -t demo-grouper-2.5 /opt/grouper/2.5/container

Files injected in sub-image

[root@i2midev6 slashRoot]# find

These files are as thin as possible

[root@i2midev6 slashRoot]# more opt/grouper/grouperWebapp/WEB-INF/classes/ 
hibernate.connection.url = jdbc:mysql://localhost:3306/grouper_v2_5?CharSet=utf8&useUnicode=true&characterEncoding=utf8

hibernate.connection.username    = grouper_v2_5

hibernate.connection.password         = ****

Docker RUN command

[root@i2midev6 container]# more

docker run --net=host \
--detach \
-u 1870 \
--mount type=bind,src=/opt/grouper/2.5/container/logs,dst=/opt/grouper/logs \
-e RUN_SHIB_SP='false' \
-e GROUPER_TOMCAT_CONTEXT=grouper_v2_5 \
-e RUN_APACHE='false' \
-e GROUPER_SCIM=true \
--name grouper_v2_5 demo-grouper-2.5:latest ui-ws
Run command argumentDescription
docker run Run the container
--net=hostNetworking in container is like a host app.  mysql localhost database is still accessible to localhost in container even though thats on the host, not in container.
--detachRun in background
-u 1870Run container as "appadmin" user on host which is uid 1870
--mount type=bind,src=/opt/grouper/2.5/container/logs,dst=/opt/grouper/logsMount the log dir from in container to out of container
-e RUN_SHIB_SP='false'Dont run shib in container since its on the host
-e GROUPER_CHOWN_DIRS=falseStarting container as non-root, dont chown dirs, this is dont in subimage
-e GROUPER_RUN_TOMCAT_NOT_SUPERVISOR=trueWe have one process here, just run tomcat and not container supervisor
-e GROUPER_TOMCAT_CONTEXT=grouper_v2_5We will have the tomee context for the webapp match the apache context (first part of URL after domain name)
-e RUN_APACHE='false'Dont run apache we have it in the host
-e GROUPER_DAEMON=trueRun the daemon
-e GROUPER_WS_GROUPER_AUTH=trueDo Grouper authn for WS
-e GROUPER_MAX_MEMORY='3g'Tomee memory.  This is a low amount for daemon/UI/WS/Scim, but the demo server is low activity
-e GROUPER_TOMCAT_AJP_PORT=8191Because we are net=host, we need this to not conflict with other tomcats on server.  Apache connects to the AJP port
-e GROUPER_TOMCAT_HTTP_PORT=8190Because we are net=host, we need this to not conflict with other tomcats on server
-e GROUPER_TOMCAT_SHUTDOWN_PORT=8192 Because we are net=host, we need this to not conflict with other tomcats on server
-e GROUPER_SCIM=true Run SCIM server
-e GROUPER_SCIM_GROUPER_AUTH=true Do Grouper authn for scim
-e  GROUPER_AUTO_DDL_UPTOVERSION='v2.5.*'Auto upgrade DDL in v2.5
-e GROUPER_LOG_TO_HOST=trueDont log to pipes, log to mounted log dir on host
--name grouper_v2_5  Container name
demo-grouper-2.5:latestSub-image name from above
ui-wsRun the UI and WS (atleast)

Add account for WS and Scim

Add a local entity

Set the password

#  docker exec -u tomcat -it grouper_v2_5 /bin/bash
[tomcat@i2midev6 WEB-INF]$ cd bin
[tomcat@i2midev6 bin]$ ./
gsh 0% new GrouperPasswordSave().assignApplication(GrouperPassword.Application.WS).assignUsername("test:local").assignPassword("********").save();           

Try WS:   (login with test:local / *******   )
Try SCIM:          (login with test:local / *******   )

Apache config


#match anything that is grouperExternal
<LocationMatch ^/grouper_v2_5[^/]*/grouperExternal/.*>
  AuthType shibboleth
  ShibRequestSetting requireSession 1
  require valid-user


ProxyPass /grouper-ws_v2_5/ ajp://localhost:8191/grouper_v2_5/

ProxyPass /grouper-ws-scim_v2_5/ ajp://localhost:8191/grouper_v2_5/

ProxyPass /grouper_v2_5/ ajp://localhost:8191/grouper_v2_5/

ProxyPass /status_grouper_v2_5/status ajp://localhost:8191/grouper_v2_5/status

Memory on host

First we will shut down some old versions to save some memory.

 1009  /sbin/service tomcat_a stop
 1010  /sbin/service tomcat_c stop
 1011  /sbin/service tomcat_d stop
 1012  /sbin/service tomcat_i stop
 1013  /sbin/service tomcat_j stop
 1014  /sbin/service tomcat_k stop
[root@i2midev6 ~]# chkconfig --del tomcat_a
[root@i2midev6 ~]# chkconfig --del tomcat_c
[root@i2midev6 ~]# chkconfig --del tomcat_d
[root@i2midev6 ~]# chkconfig --del tomcat_i
[root@i2midev6 ~]# chkconfig --del tomcat_j
[root@i2midev6 ~]# chkconfig --del tomcat_k

[root@i2midev6 ~]# free
              total        used        free      shared  buff/cache   available
Mem:       14202688     5299732     1079660        9576     7823296     8563136
Swap:       2097148           0     2097148


Lets clone our database from 2.4 to 2.5.  This is SQLYog (mysql windows tool), but you can use whatever database tool you want

Create a local database. Preferred is postgres, but could be mysql or oracle too. (e.g. mysql, utf8, bin collation, create a user and password, and grant all to the new database from username and password)

Create a user, and grant all to that database from the user (user: grouper_v2_5)

Clone the 2.4 database with the Grouper database migration utility

  • No labels