---
title: Deploy Java RCS in a Docker container
description: You can deploy the Java Remote Connector Server (RCS) in a Docker container. This topic outlines the process to obtain, customize, configure, and run RCS using a Docker environment. The RCS download includes a sample dockerfile at path/to/openicf/docker/Dockerfile.
component: openicf
page_id: openicf:connector-reference:rcs-docker
canonical_url: https://docs.pingidentity.com/openicf/connector-reference/rcs-docker.html
section_ids:
  rcs-docker-getting-started: Getting started
  rcs-docker-customizing-parent-image: Customize the parent RCS image
  rcs-docker-pushing: Pushing the RCS image to a Docker repository
  rcs-docker-registering: Registering RCS
  rcs-docker-configuring: Configuring RCS
  rcs-docker-running: Running RCS
  rcs-docker-developing: Developing scripted connectors with Docker
---

# Deploy Java RCS in a Docker container

You can deploy the Java Remote Connector Server (RCS) in a Docker container. This topic outlines the process to obtain, customize, configure, and run RCS using a Docker environment. The RCS download includes a sample dockerfile at `path/to/openicf/docker/Dockerfile`.

## Getting started

You can pull RCS images from the public [Artifact Registry](https://console.cloud.google.com/artifacts/docker/forgerock-io/us/gcr.io/rcs) (browser access requires a Google account).

A public RCS image provides the default installation of the OpenICF (ICF) framework.

## Customize the parent RCS image

To extend the parent image functionality, customize it by copying additional files to the ICF installation folder (`/opt/openicf`) in the final image. Additional files can include connector packages, scripts, drivers, and so on.

Capture RCS image customizations by saving them in a custom Docker image using a custom `Dockerfile`.

The following procedure includes the five example sections from the custom `Dockerfile` included with RCS 1.5.20.30 and later:

1. Accept build arguments and select the parent image.

   Dockerfile excerpt

   ```dockerfile
   # 1. Accept build arguments in the FROM instruction.
   # @example
   ARG FROM_TAG=1.5.20.34
   FROM gcr.io/forgerock-io/rcs:$FROM_TAG
   ```

   During the `docker build` phase, use the `--build-arg` flag to specify the `gcr.io/forgerock-io/rcs` repository parent image tag for building the RCS image. For example:

   ```bash
   docker build --build-arg FROM_TAG=1.5.20.34 -t rcs .
   ```

2. Add additional files to the RCS installation.

   Dockerfile excerpt

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

   Copy local files into the `/opt/openicf` location in the parent RCS image to extend or modify its functionality. The `openicf` installation folder structure can be replicated locally to copy everything at once, or separate `COPY` instructions can be used for individual folders and files, which can help cache respective layers in the final image.

   |   |                                                                                                                                                                                                    |
   | - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   |   | The RCS parent image `Dockerfile` specifies a working directory: `WORKDIR /opt/openicf`. In the `COPY` instruction destination, use an absolute path or a path relative to the `WORKDIR` location. |

   Files and directories

   * `openicf/conf`

     Provide a custom version of the `openicf/conf/ConnectorServer.properties` file. Specify all or some RCS configuration properties in this file, as described in [Configure a remote connector server (RCS)](configure-server.html).

   * `openicf/connectors`

     Add custom or [downloaded connectors](https://backstage.forgerock.com/downloads/browse/idm/all/productId:idm-connectors) packaged in JAR files into this sub-directory.

   * `openicf/lib`

     Add any additional dependencies used by connectors into this sub-directory. For example, required database drivers.

     Provide a customized version of the `openicf/conf/logback.xml` file to overwrite the default one. This adjusts the detail of logs produced by the RCS, as described in [Connector logs](icf-logs.html).

     You can find the resulting log files in a running container within the `/opt/openicf/logs` folder. Logs are printed to standard output by the container in the default attached mode or can be requested explicitly from the container with the `docker logs` command.

   * `openicf/scripts`

     Add scripted connector Groovy scripts to this directory.

   * `openicf/security`

     Contains the default RCS keystore and truststore.

   |   |                                                                                                                        |
   | - | ---------------------------------------------------------------------------------------------------------------------- |
   |   | You can copy any other content the connectors need to any other accessible location within the connector server image. |

3. Use root user for operations requiring escalated privileges.

   Dockerfile excerpt

   ```dockerfile
   # 3. Use root user for operations that require escalated permissions.
   # @example
   # USER root
   ```

   By default, a Docker container runs as the root user. It's recommended to run a Docker container as a non-root user, which is addressed in the RCS parent image `Dockerfile` that typically specifies `USER 11111`.

   However, some instructions require elevated permissions. For example, adding an untrusted certificate to the Java truststore requires root user privileges.

4. Add certificates to RCS truststore.

   Dockerfile excerpt

   ```
   # 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
   ```

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

   |   |                                                                                                                         |
   | - | ----------------------------------------------------------------------------------------------------------------------- |
   |   | PingOne Advanced Identity Cloud certificates are signed by a trusted CA and don't need to be added to the `truststore`. |

5. Switch to a non-root user.

   Dockerfile excerpt

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

   After performing any specific instructions that require elevated permissions, switch back to the non-root user using the `USER` instruction.

   During development, you might want to continue as a root user. For example, root privileges are required to enable file sync when using a Docker image in Skaffold development mode. In this case, specify the user in the `docker run` command with the `--user` or `-u` flag.

## Pushing the RCS image to a Docker repository

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

If the Docker repository is served from a private Docker registry, ensure Docker is configured with appropriate privileges to push to this repository. The Docker registry provider typically provides specific instructions on setting up authentication for Docker.

For example, [documentation on setting up authentication for Docker](https://cloud.google.com/artifact-registry/docs/docker/authentication) describes how to use the [`gcloud` credential helper](https://cloud.google.com/artifact-registry/docs/docker/authentication#gcloud-helper) for configuring Docker with [Google Cloud CLI](https://cloud.google.com/sdk/gcloud) session credentials. This can be used while developing RCS images and pushing them to a Google Cloud Artifact Registry.

The image must be [tagged](https://docs.docker.com/engine/reference/commandline/tag/) before [pushing it to a repository](https://docs.docker.com/engine/reference/commandline/push/). Tag the image with the reference to the repository in the `docker build` command using the `-t` or `--tag` flag. For example:

```bash
# Build and tag the image with the repository reference
$ docker build --build-arg FROM_TAG=1.5.20.34 -t gcr.io/<organization>/<username>/rcs .

# Push the tagged image
$ docker push gcr.io/<organization>/<username>/rcs
```

## Registering RCS

Configure the RCS in [client mode](configure-server.html) to connect it to a managed environment, such as Advanced Identity Cloud.

In client mode, the `connectorserver.connectorServerName` property must be provided in the RCS configuration. This property must match the registered name in IDM or Advanced Identity Cloud:

* In Advanced Identity Cloud, a connector server can be registered using the Advanced Identity Cloud admin UI (refer to the [documentation on syncing identities and registering a remote server](https://docs.pingidentity.com/pingoneaic/latest/identities/sync-identities.html#task-1-register-a-remote-server)). In the UI, the Name input for a connector server accepts a value containing lower-case alphanumeric characters, hyphens (`-`), and underscores (`_`). Advanced Identity Cloud saves the Name value as the `connectorServerName` property in the connector server configuration.

* IDM saves the Name value as the `name` property of a `remoteConnectorClients` entry in the `provisioner.openicf.connectorinfoprovider.json` file.

## Configuring RCS

To configure RCS in client mode, define at least the following RCS configuration properties:

* `connectorserver.url`

  |   |                                                                                                                                                                                                                          |
  | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
  |   | To specify more than one `connectorserver.url`, separate each value using a comma (`,`). Java RCS versions earlier than 1.5.20.26 don't support multiple values for `connectorserver.url` when using a Docker container. |

* `connectorserver.connectorServerName`

To connect to an Advanced Identity Cloud tenant, the following must also be specified:

* `connectorserver.tokenEndpoint`

* `connectorserver.clientId`

* `connectorserver.clientSecret`

* `connectorserver.scope`

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

* `connectorserver.loggerClass`

Static connector server properties can be provided using instructions included in the `openicf/conf/ConnectorServer.properties` file. In addition, the following sample configurations are available in `openicf/conf/samples`:

* `ConnectorServer.properties.onprem-server`

* `ConnectorServer.properties.onprem-client`

* `ConnectorServer.properties.default-parameters`

* `ConnectorServer.properties.cloud-client`

For example, a `ConnectorServer.properties` file could contain the following instructions for setting properties that are unlikely to change and carry no sensitive data and could, therefore, be embedded into the image:

`conf/ConnectorServer.properties`

```properties
# Set connectorserver properties.
# See OpenICF documentation for details:
# https://docs.pingidentity.com/openicf/connector-reference/configure-server.html#rcs-properties

# Set static properties.
connectorserver.scope=fr:idm:*
connectorserver.loggerClass=org.forgerock.openicf.common.logging.slf4j.SLF4JLog
```

To provide dynamic values in the connector server configuration, which is a suitable approach for secrets and environment specifics, define JVM system properties using [the `OPENICF_OPTS` environment variable](configure-server.html#use-openicfopts-env-var). This variable needs to be exported into the JVM's environment before the connector server starts. Provide this information when the container runs so it's not embedded into the image.

## Running RCS

Create and run an RCS container with the `docker run` command.

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

1. Set environment variables with an `.env` file:

   .env file content

   ```text
   OPENICF_OPTS=-Dconnectorserver.url=wss://<your-tenant-url>/openicf/0 -Dconnectorserver.tokenEndpoint=https://<your-tenant-url>/am/oauth2/realms/root/realms/alpha/access_token -Dconnectorserver.connectorServerName=rcs-docker-1 -Dconnectorserver.clientId=RCSClient -Dconnectorserver.clientSecret=YA...H?
   ```

2. User `docker run` and supply the environment file:

   ```bash
   $ docker run --env-file .env rcs
   ```

A Docker environment file is limited to one-line variable definitions and can be difficult to read. An alternative approach is defining the environment variable on the host machine and then using the `-e` or `--env` flag. For example:

1. Define `OPENICF_OPTS` in a file (`.env` in this example):

   ```bash
   # .env file content
   OPENICF_OPTS="-Dconnectorserver.url=wss://openam-dx-kl04.forgeblocks.com/openicf/0 \
   -Dconnectorserver.tokenEndpoint=https://openam-dx-kl04.forgeblocks.com/am/oauth2/realms/root/realms/alpha/access_token \
   -Dconnectorserver.connectorServerName=rcs-docker-1 \
   -Dconnectorserver.clientId=RCSClient \
   -Dconnectorserver.clientSecret=YA...H?"
   ```

2. Source the file and run the container:

   ```bash
   # Export variables from .env file into the current shell
   $ set -a; source .env; set +a;

   # Run the container using the exported variable
   $ docker run -e OPENICF_OPTS rcs
   ```

   This lets you set sensitive and dynamic properties without embedding them into the image.

   You can substitute values using `OPENICF_OPTS` to address different environments or different connector server names registered in IDM or Advanced Identity Cloud. For example, you could run multiple containers referring to different connector server names registered in a server cluster.

## Developing scripted connectors with Docker

The parent RCS image doesn't ship with any Groovy scripts. While developing scripted connectors, use the `docker run` flag `-v` or `--volume` as a convenient way of providing script content to the running RCS container. For example:

```bash
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 become available to the RCS running in the container.
