ForgeOps

Base Docker images

ForgeRock provides 12 Docker images for deploying the Ping Identity Platform:

  • Seven unsupported, evaluation-only base images:

    Base image Available at

    amster

    am-cdk

    am-config-upgrader

    ds

    idm-cdk

    ForgeRock container registry at gcr.io/forgerock-io/idm-cdk:7.5.0

    ig

    java-17

    Provided in the forgeops-extras repository.

  • Five supported base images that implement the platform’s user interface elements and ForgeOps operators:

    Base image Available at

    ds-operator

    us-docker.pkg.dev/forgeops-public/images

    platform-admin-ui

    gcr.io/forgerock-io

    platform-enduser-ui

    gcr.io/forgerock-io

    platform-login-ui

    gcr.io/forgerock-io

    secret-agent

    us-docker.pkg.dev/forgeops-public/images

Before you begin building custom images, ensure that you are using Java version 17 on your computer. For example:

$ java --version
openjdk 17.0.10 2024-01-16
OpenJDK Runtime Environment Temurin-17.0.10+7 (build 17.0.10+7)
OpenJDK 64-Bit Server VM Temurin-17.0.10+7 (build 17.0.10+7, mixed mode)

Which Docker images do I deploy?

  • I am a developer using a single-instance ForgeOps deployment.

    • UI elements. Deploy the supported images from ForgeRock.

    • Other platform elements. Either deploy:

      • The evaluation-only images from ForgeRock.

      • Docker images that are based on the evaluation-only images, but contain a customized configuration profile.

  • I am doing a proof-of-concept ForgeOps deployment.

    • UI elements. Deploy the supported images from ForgeRock.

    • Other platform elements. Either deploy:

      • The evaluation-only images from ForgeRock.

      • Docker images that are based on the evaluation-only images, but contain a customized configuration profile.

  • I am deploying the platform in production.

    • UI elements. Deploy the supported images from ForgeRock.

    • Other platform elements. Deploy Docker images that are based on your own base images, but contain a customized configuration profile. ForgeRock does not support production deployments with Docker images based on the evaluation-only images.

Your own base Docker images

While the procedures here show the use of Docker container engine, you can use Podman container engine to create images for ForgeOps deployment.

Perform the following steps to build base images for the eight unsupported, evaluation-only Docker images. After you’ve built your own base images, push them to your Docker repository:

  1. Download the latest versions of the AM, Amster, IDM, and DS .zip files from the ForgeRock Download Center. Optionally, you can also download the latest version of the ${ig.abbr} .zip file.

  2. If you haven’t already done so, clone the forgeops and forgeops-extras repositories. For example:

    $ git clone https://github.com/ForgeRock/forgeops.git
    $ git clone https://github.com/ForgeRock/forgeops-extras.git

    Both repositories are public; you do not need credentials to clone them.

  3. Check out the forgeops repository’s release/7.5-20240618 branch:

    $ cd /path/to/forgeops
    $ git checkout release/7.5-20240618
  4. Check out the forgeops-extras repository’s master branch:

    $ cd /path/to/forgeops-extras
    $ git checkout master
  5. Build the Java base image, which is required by several of the other Dockerfiles:

    $ cd /path/to/forgeops-extras/images/java-17
    $ docker build --tag my-repo/java-17 .
    
    ⇒ [internal] load build definition from Dockerfile                                                                                                       0.0s
     ⇒ ⇒ transferring dockerfile: 2.38kB                                                                                                                     0.0s
     ⇒ [internal] load .dockerignore                                                                                                                         0.0s
     ⇒ ⇒ transferring context: 2B                                                                                                                            0.0s
     ⇒ [internal] load metadata for docker.io/library/debian:bullseye-slim                                                                                   1.1s
     ⇒ [internal] load metadata for docker.io/azul/zulu-openjdk-debian:17                                                                                    1.3s
     ⇒ [jdk 1/3] FROM docker.io/azul/zulu-openjdk-debian:17@sha256:420a137d0576e3fd0d6f6332f5aa1aef85314ed83b3797d7f965e0b9169cbc57                         17.7s
    ...
    ⇒ exporting to image                                                                                                                                     0.3s
     ⇒ ⇒ exporting layers                                                                                                                                    0.3s
     ⇒ ⇒ writing image sha256:cc52e9623b3cd411682ca221a6722e83610b6b7620f126d3f7c4686e79ff1797                                                               0.0s
     ⇒ ⇒ naming to my-repo/java-17                                                                                                                 0.0s
  6. Build the base image for Amster. This image must be available in order to build the base image for AM in the next step:

    1. Unzip the Amster .zip file.

    2. Change to the amster/samples/docker directory in the expanded .zip file output.

    3. Run the setup.sh script:

      $ ./setup.sh
      
      + mkdir -p build
      + find ../.. '!' -name .. '!' -name samples '!' -name docker -maxdepth 1 -exec cp -R '{}' build/ ';'
      + cp ../../docker/amster-install.sh ../../docker/docker-entrypoint.sh ../../docker/export.sh ../../docker/tar.sh build
    4. Edit the Dockerfile in the samples/docker directory. Change the line:

      FROM gcr.io/forgerock-io/java-17:latest

      to:

      FROM my-repo/java-17
    5. Build the amster Docker image:

      $ docker build --tag amster:7.5.0 .
      
       ⇒ [internal] load build definition from Dockerfile                                                                                          0.0s
       ⇒ ⇒ transferring dockerfile: 1.67kB                                                                                                         0.0s
       ⇒ [internal] load .dockerignore                                                                                                             0.0s
       ⇒ ⇒ transferring context: 2B                                                                                                                0.0s
       ⇒ [internal] load metadata for docker.io/my-repo/java-17:latest                                                                             1.1s
       ⇒ [1/8] FROM docker.io/my-repo/java-17
      ...
       ⇒ exporting to image
       ⇒ ⇒ exporting layers
       ⇒ ⇒ writing image sha256:bc47...f9e52                                                                                                       0.0s
       ⇒ ⇒ naming to docker.io/library/amster:7.5.0
  7. Build the empty AM image:

    1. Unzip the AM .zip file.

    2. Change to the openam/samples/docker directory in the expanded .zip file output.

    3. Run the setup.sh script:

      $ chmod +x ./setup.sh
      ./setup.sh
    4. Change to the images/am-empty directory.

    5. Build the am-empty Docker image:

      $ docker build --tag am-empty:7.5.0 .
      
       ⇒ [internal] load build definition from Dockerfile                                                                                          0.0s
       ⇒ ⇒ transferring dockerfile: 3.60kB                                                                                                         0.0s
       ⇒ [internal] load .dockerignore                                                                                                             0.0s
       ⇒ ⇒ transferring context: 2B                                                                                                                0.0s
       ⇒ [internal] load metadata for docker.io/library/tomcat:9-jdk17-openjdk-slim-bullseye                                                       1.8s
       ⇒ [internal] load build context                                                                                                             5.6s
       ⇒ ⇒ transferring context: 231.59MB                                                                                                          5.6s
       ⇒ [base  1/14] FROM docker.io/library/tomcat:9-jdk17-openjdk-slim-bullseye@...
      ...
       ⇒ exporting to image                                                                                                                        1.7s
       ⇒ ⇒ exporting layers                                                                                                                        1.6s
       ⇒ ⇒ writing image sha256:9784a73...1d36018c9                                                                                                0.0s
       ⇒ ⇒ naming to docker.io/library/am-empty:7.5.0
  8. Build the base image for AM:

    1. Change to the ../am-base directory.

    2. Edit the Dockerfile in the ../am-base directory and change the line:

      FROM ${docker.push.repo}/am-empty:${docker.tag}

      to:

      FROM am-empty:7.5.0
    3. Build the am-base Docker image:

      $ docker build --build-arg docker_tag=7.5.0 --tag am-base:7.5.0 .
      
       ⇒ [internal] load build definition from Dockerfile                                                               0.0s
       ⇒ ⇒ transferring dockerfile: 2.72kB                                                                              0.0s
       ⇒ [internal] load .dockerignore                                                                                  0.0s
       ⇒ ⇒ transferring context: 2B                                                                                     0.0s
       ⇒ [internal] load metadata for docker.io/library/amster:7.5.0                                                    0.0s
       ⇒ [internal] load metadata for docker.io/library/am-empty:7.5.0                                                  0.0s
       ⇒ [internal] load build context                                                                                  0.4s
       ⇒ ⇒ transferring context: 35.66MB                                                                                0.4s
       ⇒ [generator  1/15] FROM docker.io/library/am-empty:7.5.0                                                        0.4s
       ⇒ [amster 1/1] FROM docker.io/library/amster:7.5.0                                                               0.2s
       ⇒ [generator  2/15] RUN apt-get update -y &&     apt-get install -y git jq unzip
      ...
       ⇒ [am-base  7/11] COPY --chown=forgerock:root docker-entrypoint.sh /home/forgerock/                              0.0s
       ⇒ [am-base  8/11] COPY --chown=forgerock:root scripts/import-pem-certs.sh /home/forgerock/                       0.0s
       ⇒ [am-base  9/11] RUN rm "/usr/local/tomcat"/webapps/am/WEB-INF/lib/click-extras-*.jar                           0.2s
       ⇒ [am-base 10/11] RUN rm "/usr/local/tomcat"/webapps/am/WEB-INF/lib/click-nodeps-*.jar                           0.3s
       ⇒ [am-base 11/11] RUN rm "/usr/local/tomcat"/webapps/am/WEB-INF/lib/velocity-*.jar                               0.2s
       ⇒ exporting to image                                                                                             0.2s
       ⇒ ⇒ exporting layers                                                                                             0.2s
       ⇒ ⇒ writing image sha256:2c06...87c6c                                                                            0.0s
       ⇒ ⇒ naming to docker.io/library/am-base:7.5.0
    4. Change to the ../am-cdk directory.

    5. Edit the Dockerfile in the ../am-cdk directory. Change the line:

      FROM ${docker.push.registry}/forgerock-io/am-base/${docker.promotion.folder}:${docker.tag}

      to:

      FROM am-base:7.5.0
    6. Build the am Docker image:

      $ docker build --build-arg docker_tag=7.5.0 --tag my-repo/am:7.5.0 .
      [+] Building 5.1s (10/10) FINISHED                                                                 docker:desktop-linux
       ⇒ [internal] load build definition from Dockerfile                                                               0.0s
       ⇒ ⇒ transferring dockerfile: 1.71kB                                                                              0.0s
       ⇒ [internal] load .dockerignore                                                                                  0.0s
       ⇒ ⇒ transferring context: 2B                                                                                     0.0s
       ⇒ [internal] load metadata for docker.io/library/am-base:7.5.0                                                   0.0s
       ⇒ [1/5] FROM docker.io/library/am-base:7.5.0                                                                     0.2s
       ⇒ [internal] load build context                                                                                  0.2s
       ⇒ ⇒ transferring context: 403.07kB                                                                               0.1s
       ⇒ [2/5] RUN apt-get update         && apt-get install -y git         && apt-get clean         && rm -r /var/lib  3.9s
       ⇒ [3/5] RUN cp -R /usr/local/tomcat/webapps/am/XUI /usr/local/tomcat/webapps/am/OAuth2_XUI                       0.3s
       ⇒ [4/5] COPY --chown=forgerock:root /config /home/forgerock/cdk/config                                           0.0s
       ⇒ [5/5] RUN rm -rf /home/forgerock/openam/config/services &&     mkdir /home/forgerock/openam/config/services    0.5s
       ⇒ exporting to image                                                                                             0.1s
       ⇒ ⇒ exporting layers                                                                                             0.1s
       ⇒ ⇒ writing image sha256:14b43fb5121cee08341130bf502b7841429b057ff406bbe635b23119a74dec45                        0.0s
       ⇒ ⇒ naming to my-repo/am:7.5.0                                                                                   0.0s
  9. Now that the AM image is built, tag the base image for Amster in advance of pushing it to your private repository:

    $ docker tag amster:7.5.0 my-repo/amster:7.5.0
  10. Build the am-config-upgrader base image:

    1. Change to the openam directory in the expanded AM .zip file output.

    2. Unzip the Config-Upgrader-7.5.0.zip file.

    3. Change to the amupgrade/samples/docker directory in the expanded Config-Upgrader-7.5.0.zip file output.

    4. Edit the Dockerfile in the amupgrade/samples/docker directory and change line 16 from:

      FROM gcr.io/forgerock-io/java-17:latest

      to:

      FROM my-repo/java-17
    5. Run the setup.sh script:

      $ ./setup.sh
      
      + mkdir -p build/amupgrade
      + find ../.. '!' -name .. '!' -name samples '!' -name docker -maxdepth 1 -exec cp -R '{}' build/amupgrade ';'
      + cp ../../docker/docker-entrypoint.sh .
    6. Create the base am-config-upgrader image:

      $ docker build --tag my-repo/am-config-upgrader:7.5.0 .
      
      [+] Building 8.5s (9/9) FINISHED                                  docker:desktop-linux
       ⇒ [internal] load build definition from Dockerfile                               0.0s
       ⇒ ⇒ transferring dockerfile: 1.10kB                                              0.0s
       ⇒ [internal] load .dockerignore                                                  0.0s
       ⇒ ⇒ transferring context: 2B                                                     0.0s
       ⇒ [internal] load metadata for my-repo/java-17:latest                            0.0s
       ⇒ CACHED [1/4] FROM my-repo/java-17                                              0.0s
       ⇒ [internal] load build context                                                  0.3s
       ⇒ ⇒ transferring context: 20.58MB                                                0.3s
       ⇒ [2/4] RUN apt-get update &&     apt-get upgrade -y                             8.3s
       ⇒ [3/4] COPY --chown=forgerock:root docker-entrypoint.sh /home/forgerock/        0.0s
       ⇒ [4/4] COPY build/ /home/forgerock/                                             0.0s
       ⇒ exporting to image                                                             0.1s
       ⇒ ⇒ exporting layers                                                             0.1s
       ⇒ ⇒ writing image sha256:3f6845…​44011                                            0.0s
       ⇒ ⇒ naming to my-repo/am-config-upgrader:7.5.0                                   0.0s
  11. Build the base image for DS:

    1. Unzip the DS .zip file.

    2. Change to the opendj directory in the expanded .zip file output.

    3. Run the samples/docker/setup.sh script to create a server:

      $ ./samples/docker/setup.sh
      
      + rm -f template/config/tools.properties
      + cp -r samples/docker/Dockerfile samples/docker/README.md ...
      + rm -rf — README README.md bat '*.zip' opendj_logo.png setup.bat upgrade.bat setup.sh
      + ./setup --serverId docker --hostname localhost
      ...
      
      Validating parameters... Done
      Configuring certificates... Done
      ...
    4. Edit the Dockerfile in the opendj directory. Change the line:

      FROM gcr.io/forgerock-io/java-17:latest

      to:

      FROM my-repo/java-17
    5. Build the ds-empty base image:

      $ docker build --tag my-repo/ds-empty:7.5.0 .
      
      [+] Building 11.0s (9/9) FINISHED
      
       ⇒ [internal] load build definition from Dockerfile                                                                                          0.0s
       ⇒ ⇒ transferring dockerfile: 1.23kB                                                                                                         0.0s
       ⇒ [internal] load .dockerignore                                                                                                             0.0s
       ⇒ ⇒ transferring context: 2B                                                                                                                0.0s
       ⇒ [internal] load metadata for my-repo/java-17:latest                                                                                       1.7s
       ⇒ [internal] load build context                                                                                                             1.2s
       ⇒ ⇒ transferring context: 60.85MB                                                                                                           1.2s
       ⇒ CACHED [1/4] FROM my-repo/java-17:latest
      ...
       ⇒ [4/4] WORKDIR /opt/opendj                                                                                                                 0.0s
       ⇒ exporting to image                                                                                                                        0.4s
       ⇒ ⇒ exporting layers                                                                                                                        0.3s
       ⇒ ⇒ writing image sha256:713ac...b107e0f                                                                                                    0.0s
       ⇒ ⇒ naming to my-repo/ds-empty:7.5.0
  12. Build the base image for IDM:

    1. Create a new shell script file named build-idm-image.sh and copy the following lines into it:

      #!/bin/bash
      
      if [ $# -lt 3 ]; then
        echo "$0 <source image> <new base image> <result image>"
        exit 0
      fi
      
      sourceImage="$1"
      javaImage="$2"
      resultImage="$3"
      
      container_id=$(docker create $sourceImage)
      docker export $container_id -o image.tar
      docker rm $container_id
      
      tar xvf image.tar opt/openidm
      rm -f image.tar
      
      cd opt/openidm
      # use | separators because image names often have / and :
      sed -i.bak 's|^FROM.*$|FROM '$javaImage'|' bin/Custom.Dockerfile
      rm bin/Custom.Dockerfile.bak
      
      docker build . --file bin/Custom.Dockerfile --tag "$resultImage"
      rm -rf opt
    2. Change the mode of the file to be executable and run it.

      $ chmod +x build-idm-image.sh
      $ ./build-idm-image.sh gcr.io/forgerock-io/idm-cdk:7.5.0 my-repo/java-17  my-repo/idm:7.5.0
      The build-idm-image.sh script expands the IDM Docker image, rebuilds the image, and cleans up afterward.
  13. (Optional) Build the base image for ${ig.abbr}:

    1. Unzip the ${ig.abbr} .zip file.

    2. Change to the identity-gateway directory in the expanded .zip file output.

    3. Edit the Dockerfile in the identity-gateway/docker directory. Change the line:

      FROM gcr.io/forgerock-io/java-17:latest

      to:

      FROM my-repo/java-17
    4. Build the ig base image:

      $ docker build . --file docker/Dockerfile --tag my-repo/ig:2024.3.0
      
      [+] Building 2.1s (8/8) FINISHED
      ⇒ [internal] load build definition from Dockerfile                                                                                          0.0s
       ⇒ ⇒ transferring dockerfile: 1.43kB                                                                                                        0.0s
       ⇒ [internal] load .dockerignore                                                                                                            0.0s
       ⇒ ⇒ transferring context: 2B                                                                                                               0.0s
       ⇒ [internal] load metadata for my-repo/java-17:latest                                                                                      0.3s
       ⇒ [internal] load build context                                                                                                            2.2s
       ⇒ ⇒ transferring context: 113.60MB                                                                                                         2.2s
       ⇒ CACHED [1/3] FROM my-repo/java-17:latest
       ⇒ [2/3] COPY --chown=forgerock:root . /opt/ig                                                                                              0.7s
       ⇒ [3/3] RUN mkdir -p "/var/ig"     && chown -R forgerock:root "/var/ig" "/opt/ig"     &&  -R g+rwx "/var/ig" "/opt/ig"                     0.9s
       ⇒ exporting to image                                                                                                                       0.6s
       ⇒ ⇒ exporting layers                                                                                                                       0.6s
       ⇒ ⇒ writing image sha256:77fc5...6e63                                                                                                      0.0s
       ⇒ ⇒ naming to my-repo/ig:2024.3.0
  14. Run the docker images command to verify that you built the base images:

    $ docker images | grep my-repo
    
    REPOSITORY                   TAG      IMAGE ID        CREATED        SIZE
    my-repo/am                   7.5.0    552073a1c000    1 hour ago     795MB
    my-repo/am-config-upgrader   7.5.0    d115125b1c3f    1 hour ago     795MB
    my-repo/amster               7.5.0    d9e1c735f415    1 hour ago     577MB
    my-repo/ds-empty             7.5.0    ac8e8ab0fda6    1 hour ago     196MB
    my-repo/idm                  7.5.0    0cc1b7f70ce6    1 hour ago     387MB
    my-repo/ig                   2024.3.0 cc52e9623b3c    1 hour ago     249MB
    my-repo/java-17              latest   a504925c2672    1 hour ago     144MB
  15. Push the new base Docker images to your Docker repository.

    Refer to your registry provider documentation for detailed instructions. For most Docker registries, you run the docker login command to log in to the registry. Then, you run the docker push command to push a Docker image to the registry.

    Be sure to configure your Docker registry so that you can successfully push your Docker images. Each cloud-based Docker registry has its own specific requirements. For example, on Amazon ECR, you must create a repository for each image.

    Push the following images to your repository:

    • my-repo/am:7.5.0

    • my-repo/am-config-upgrader:7.5.0

    • my-repo/amster:7.5.0

    • my-repo/ds-empty:7.5.0

    • my-repo/idm:7.5.0

    • my-repo/java-17

    If you’re deploying your own ${ig.abbr} base image, also push the my-repo/ig:2024.3.0 image.

Create Docker images for use in production

After you’ve built and pushed your own base images to your Docker registry, you’re ready to build customized Docker images that can be used in a production deployment of the Ping Identity Platform. These images:

Create your production-ready Docker images, create a Kubernetes cluster to test them, and delete the cluster when you’ve finished testing the images:

  1. Clone the forgeops repository.

  2. Obtain custom configuration profiles that you want to use in your Docker images from your developer, and copy them into your forgeops repository clone:

    • Obtain the AM configuration profile from the /path/to/forgeops/docker/am/config-profiles directory.

    • Obtain the IDM configuration profile from the /path/to/forgeops/docker/idm/config-profiles directory.

    • (Optional) Obtain the ${ig.abbr} configuration profile from the /path/to/forgeops/docker/ig/config-profiles directory.

  3. Change the FROM lines of Dockerfiles in the forgeops repositories to refer to your own base Docker images:

    In the forgeops repository file: Change the FROM line to:

    docker/am/Dockerfile

    FROM my-repo/am:7.5.0 [1]

    docker/amster/Dockerfile

    FROM my-repo/amster:7.5.0

    docker/ds/ds-new/Dockerfile

    FROM my-repo/ds-empty:7.5.0

    docker/idm/Dockerfile

    FROM my-repo/idm:7.5.0 [2]

    (Optional) docker/ig/Dockerfile

    FROM my-repo/ig:2024.3.0

  4. If necessary, log in to your Docker registry.

  5. Build Docker images that are based on your own base images.

    While the forgeops build command uses the Docker engine by default for ForgeOps deployments, it supports Podman as well. If you are using Podman engine instead of Docker in your environment, then set the CONTAINER_ENGINE environment variable to podman before running the forgeops build command, for example:

    $ export CONTAINER_ENGINE="podman"

    The AM and IDM images contain your customized configuration profiles:

    $ cd /path/to/forgeops/bin
    $ ./forgeops build ds --push-to my-repo
    $ ./forgeops build amster --push-to my-repo
    $ ./forgeops build am --push-to my-repo --config-profile my-profile
    $ ./forgeops build idm --push-to my-repo --config-profile my-profile

    The forgeops build command:

    • Builds Docker images. The AM and IDM images incorporate customized configuration profiles.

    • Pushes Docker images to the repository specified in the --push-to argument.

    • Updates the image defaulter file, which the forgeops install command uses to determine which Docker images to run.

  6. (Optional) Build and push an ${ig.abbr} Docker image that’s based on your own base image and contains your customized configuration profile:

    $ ./forgeops build ig --config-profile my-profile --push-to my-repo
  7. Prepare a Kubernetes cluster to test your images:

    1. Create the cluster. This example assumes that you create a cluster suitable for a small-sized ForgeOps deployment.

    2. Make sure your cluster can access and pull Docker images from your repository.

    3. Create a namespace in the new cluster, and then make the new namespace the active namespace in your local Kubernetes context.

  8. Perform a ForgeOps deployment in your cluster:

    $ ./forgeops install --small --fqdn forgeops.example.com
  9. Access the AM admin UI and the IDM admin UI, and verify that your customized configuration profiles are active.

  10. Delete the Kubernetes cluster that you used to test images.

At the end of this process, the artifacts that you’ll need to deploy the Ping Identity Platform in production are available:

  • Docker images for the Ping Identity Platform, in your Docker repository

  • An updated image defaulter file, in your forgeops repository clone

You’ll need to copy the image defaulter file to your production deployment, so that when you run the forgeops install command, it will use the correct Docker images.

Typically, you model the image creation process in a CI/CD pipeline. Then, you run the pipeline at milestones in the development of your customized configuration profile.


1. The FROM statement originally contained am-cdk as part of the repository name. Be sure to use am, not am-cdk, in the revised statement.
2. The FROM statement originally contained idm-cdk as part of the repository name. Be sure to use idm, not idm-cdk, in the revised statement.