Deploying Java Remote Connector Server in a Docker Container

The Forgerock Java Remote Connector Server (RCS) can be deployed within a Docker container.


RCS Parent Image

Back to Contents

Currently, RCS images could be pulled from the image repository in the public ForgeRock Container Registry (you will need a Google account to see it in a browser).

A public RCS image provides the default installation of the ForgeRock Open Identity Connector Framework (ICF).

Customizing the Parent RCS Image

Back to Contents

If you need to extend the parent image functionality, you can customize it by copying additional files to the ICF installation folder in the final image, which is located at /opt/openicf. The additional files could include complete connector packages, scripts, drivers, etc.

The easiest and the most readable way to capture your RCS image customizations is to save them in a custom docker image using a custom Dockerfile.

For example:

# 1. Accept build arguments in the FROM instruction.
# @example

# 2. Merge your custom files with the RCS installation.
# @example
COPY openicf/conf conf
COPY openicf/connectors connectors
COPY openicf/lib lib
COPY openicf/scripts scripts

# 3. Use root user for operations that escalate permissions.
# @example
# USER root

# 4. Add untrusted public TLS certificate(s) to RCS' `truststore` to allow for communications with unrecognized hosts.
# Run `docker build` with the `--progress plain` option to check the outcome of the RUN instruction.
# @example
# COPY openicf/security/BadSSL-Untrusted-Root-Certificate-Authority.cer /opt/openicf/security
# RUN keytool -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit -trustcacerts -import -file /opt/openicf/security/BadSSL-Untrusted-Root-Certificate-Authority.cer -alias badssl-com-untrusted-root-ca -noprompt

# 5. Switch back to a non-root user.
# @example
# USER 11111

  1. During the docker build phase, you can use the –build-arg flag, where you can specify the parent image tag against which you want to build your RCS image. Doing so will allow to choose a particular version of the parent image available at the repository.

    For example:

    docker build --build-arg FROM_TAG= -t rcs .
  2. You can copy your local files into the /opt/openicf location in the parent RCS image to extend and/or modify its functionality. You can replicate the openicf installation folder structure locally and copy everything at once, or use separate COPY instructions for individual folders and files, doing which could help with caching respective layers in the final image.

    NOTE that the RCS parent image Dockerfile specifies a working directory:

    [ . . . ]
    WORKDIR /opt/openicf
    [ . . . ]

    This means that in the COPY instruction destination, you need to use an absolute path or a path relative to the WORKDIR location.

    • openicf/conf

      Provide your custom version of the openicf/conf/ file, in which you can specify all or some of the RCS configuration properties as described in the Configure a remote connector server RCS doc.

    • openicf/connectors

      Add your custom/downloaded connectors packaged in JAR files into this sub-folder.

    • openicf/lib

      • Add any additional JARs used by your connectors into this sub-folder.

        For example, you can supply database driver(s) that your connectors use.

      • Provide your customized version of the openicf/lib/framework/logback.xml file to overwrite the default one; and thus, adjust the detail of the logs produced by the RCS, as described in the Connector development > Connector troubleshooting doc and in the How do I enable debug logging and log rotation for the Java Remote Connector Server (RCS)? Knowledge Base article.

        The resulting log files could be found in a running container under the /opt/openicf/logs folder, will be printed out in the standard output by the container in the (default) attached mode, or could be explicitly requested from the container with the docker logs command.

    • openicf/scripts

      Add Groovy scripts used by your scripted connectors to this folder.

  3. By default, a Docker container runs as a root user.

    It is generally recommended to run a Docker container as a non-root user, which is addressed in the RCS parent image Dockerfile:

    [ . . . ]
    USER 11111
    [ . . . ]

    For some instructions, however, you might need elevated permissions. For example, for adding an untrusted certificate to the Java truststore, you will need the root user privileges.

  4. You can copy any other content that your connectors might use to any other accessible location within the connector server image.

    In the provided example, a public certificate is added to the Java truststore to allow for RCS communications with an otherwise untrusted host; for example, a third-party API. The destination of the COPY instruction in this case could be any accessible location within the image, because the change is not applied by the ICF, but with a command provided in the RUN instruction.

    Currently, RCS does not have its own truststore, and by default is using its Java Virtual Machine (JVM) truststore.

    The Identity Cloud certificates are signed by a trusted CA and do NOT need to be added to the truststore.

  5. After any specific instructions that require elevated permissions have been performed, you should switch back to the non-root user using the USER instruction.

    During the development phase, you might choose to continue as a root user. For example, root user privileges are required for enabling file sync when using a Docker image in the Skaffold dev mode.

    In this case, you can specify the user in the docker run command with the –user , -u flag.

Pushing RCS Image to a Docker Repository

Back to Contents

To share your RCS image and make it available for orchestration tools, you can push it to a Docker repository.

If your Docker repository is served from a private Docker registry, make sure you have configured Docker to have appropriate privileges to push to this repository. Your Docker registry provider can provide specific instructions on setting up authentication for Docker.

For example, Set up authentication for Docker describes how to use gcloud credential helper for configuring Docker with the Google Cloud CLI session credentials, which you can use while developing your RCS images and pushing them to a Google Cloud Artifact Registry.

You will need to tag your image before you push it to a repository. You can also tag your image with the reference to your repository in the docker build command using the -t, --tag flag.

For example:

$ docker build --build-arg FROM_TAG= -t<organization>/<username>/rcs .

$ docker push<organization>/<username>/rcs

Registering RCS

Back to Contents

You need to configure your RCS in client mode in order to be able to connect it to a managed environment such as ForgeRock Identity Cloud (Identity Cloud).

In the client mode, you must provide the connectorserver.connectorServerName property in your RCS configuration, which must match the name under which your connector server is registered in IDM.

In Identity Cloud, you can register a connector server using the ForgeRock Identity Platform (Platform) admin UI, as described in the Sync identities with an external resource > Register a remote server doc. In the UI, the Name input for a connector server accepts a ^[a-z0-9_-]+$ value, which can then be used in the connectorServerName property in your connector server configuration.

Eventually, the Name value is saved as the name property of a remoteConnectorClients entry in the provisioner.openicf.connectorinfoprovider.json file in IDM.

Configuring RCS

Back to Contents

To configure your RCS in the client mode, you will need to define the following RCS configuration properties:

  • connectorserver.url
  • connectorserver.connectorServerName

In order to connect to an Identity Cloud tenant, you will also need to specify the following:

  • connectorserver.tokenEndpoint
  • connectorserver.clientId
  • connectorserver.clientSecret
  • connectorserver.scope

To enable more controlled debug output, you should also specify the RCS logger class:

  • connectorserver.loggerClass

The static connector server properties could be provided via instructions included in the openicf/conf/ file.

As an example, a file could contain the following instructions for setting the properties that are not likely to change and carry no sensitive data; hence, could be embedded into the image:


# Set connectorserver properties.
# @see {@link}

# Set static properties.

To provide dynamic values in the connector server configuration, which could be the preferred approach for secrets and environment specifics, you can define JVM’s system properties via the OPENICF_OPTS environment variable, which needs to be exported into the JVM’s environment before the connector server starts. This information should be provided at the time when the container runs, so that it is not embedded into the image.

Running RCS

Back to Contents

You can create an RCS container and run it with the docker run command.

In a standalone Docker container, environment variables can be set with one of the -e, --env, --env-file flags.

For example:

.env file

OPENICF_OPTS=-Dconnectorserver.url=wss:// -Dconnectorserver.tokenEndpoint= -Dconnectorserver.connectorServerName=rcs-docker-1 -Dconnectorserver.clientId=RCSClient -Dconnectorserver.clientSecret=YA...H?
$ docker run --env-file .env rcs

A Docker environment file is limited to one-line variable definitions and might not be easy to read. An alternative approach could be defining the environment variable on the host machine and then using the -e, --env flag.

For example:


OPENICF_OPTS="-Dconnectorserver.url=wss:// \
-Dconnectorserver.tokenEndpoint= \
-Dconnectorserver.connectorServerName=rcs-docker-1 \
-Dconnectorserver.clientId=RCSClient \
$ set -a; source .env; set +a;

$ docker run -e OPENICF_OPTS rcs

This way, the sensitive and dynamic properties will not have to be embedded into the image.

In turn, every value used in the OPENICF_OPTS variable could be substituted dynamically to address different environments and/or different connector server names registered in IDM. For example, you might be interested in running multiple containers referring to different connector server names registered in a server cluster.

Developing Scripted Connectors with Docker

Back to Contents

The parent RCS image does not ship with any (Groovy) scripts. This means that while developing scripted connectors, you can use docker run (-v, --volume) flag as a convenient way of dynamically providing content of your scripts to the running RCS container.

For example:

docker run --rm --env-file .env -v ./openicf/scripts:/opt/openicf/scripts rcs

Now, any updates to the scripts made in the ./openicf/scripts folder on the host machine will become immediately available to the RCS running in the container.

While developing your scripts, you can also benefit from attaching a debugger to your RCS process, as described in the Attaching Debugger to RCS within Docker Container chapter of a developing scripted connectors article on the ForgeRock Community site.

1 Like

This is very helpful.

Along with this I was also looking for official prerequisite specification of Windows server to deploy RCS / ICF but seems I could not find it. Could you please share if you already have found it.

Hi @tanu.garg - the requirements for deploying a Remote Connector Server can be found here:

As noted in the doc, specs like memory, CPU, and disk space will be dependent upon your particular use case. Generally speaking the RCS itself is fairly lightweight.


@tanu.garg, if you follow @mwtech’s reference, installing Java RCS on Windows is covered here: Install Java RCS :: ICF One additional note is that for script development, you might want to run RCS as a Windows service, as it should allow for providing additional JVM options on the service level (the start-up script for Windows does not accept any).


I am planning to add more details on development Java RCS scripted connectors with Docker, and will either add to this article or provide reference to a separate one.