From c7421217f9df759bf6b52317d4b17b676e4beda4 Mon Sep 17 00:00:00 2001 From: Valera V Harseko Date: Thu, 8 Oct 2026 10:47:13 +0300 Subject: [PATCH 1/3] Describe running, upgrading and removing the Docker image in the Installation Guide Add the procedures "To Run OpenDJ in Docker", "To Upgrade a Docker Container" and "To Remove a Docker Container", point the preface to the first of them, and add notes to the replication and certificates chapters of the Administration Guide about what the image manages itself. The environment variables, health check, replication and certificates of the image stay described in opendj-packages/opendj-docker/README.md only, which the new text links to instead of repeating it. --- .../admin-guide/chap-change-certs.adoc | 5 ++ .../admin-guide/chap-replication.adoc | 5 ++ .../asciidoc/install-guide/chap-install.adoc | 50 +++++++++++ .../install-guide/chap-uninstall.adoc | 30 +++++++ .../asciidoc/install-guide/chap-upgrade.adoc | 82 ++++++++++++++++++- .../main/asciidoc/install-guide/preface.adoc | 4 +- 6 files changed, 173 insertions(+), 3 deletions(-) diff --git a/opendj-doc-generated-ref/src/main/asciidoc/admin-guide/chap-change-certs.adoc b/opendj-doc-generated-ref/src/main/asciidoc/admin-guide/chap-change-certs.adoc index 6566a9e745..336fd516f5 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/admin-guide/chap-change-certs.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/admin-guide/chap-change-certs.adoc @@ -33,6 +33,11 @@ This chapter covers how to replace OpenDJ key pairs and public key certificates. * Use a CA-signed certificate for replication +[NOTE] +====== +When a volume is mounted at `SECRET_VOLUME` (`/var/secrets/opendj` by default), a container started from the Docker image copies the `key*` and `trust*` files of that volume, such as `keystore`, `keystore.pin`, `truststore` and `truststore.pin`, into its instance on every start, and by default also while the server runs, when they change. Replace the key pair that secures connections with client applications on that volume rather than in the instance, where the next copy would overwrite it. Only these files are copied: the `admin-keystore`, `admin-truststore` and `ads-truststore` of the administration connector and of replication stay in the instance, and are replaced there as described in this chapter. A renewed keystore is served without a restart only if it holds the key under an alias that the previous one used as well. See the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/master/opendj-packages/opendj-docker/README.md#certificates[Certificates section of the README of the image, window=\_blank]. +====== + OpenDJ uses keystores (for private keys) and truststores (for public, signed certificates). Up to three sets of keystores are used, as shown in the following illustration. [#figure-keystores] diff --git a/opendj-doc-generated-ref/src/main/asciidoc/admin-guide/chap-replication.adoc b/opendj-doc-generated-ref/src/main/asciidoc/admin-guide/chap-replication.adoc index ddee29c327..8543fb6333 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/admin-guide/chap-replication.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/admin-guide/chap-replication.adoc @@ -39,6 +39,11 @@ OpenDJ uses advanced data replication with automated conflict resolution to help * Recover from situations where a user error has been applied to all replicas +[NOTE] +====== +The Docker image can join its replication topology itself, on every start of a container, when it is started with `OPENDJ_REPLICATION_TYPE=simple` and the servers of the topology listed in `REPLICATION_PEERS`. With `REPLICATION_PEERS` set, a container also removes from the topology the servers that are registered in it by name but not listed. To add a server to such a topology, first replace every container with one that lists the new server in its `REPLICATION_PEERS`, and only then start the new server: a container that still runs with the old list removes the new server from the topology when it starts again. To remove a server, remove its container first, then replace every other container with one that leaves it out of the list. The environment of a container cannot be changed, so restarting a container does not change its list; a server registered by an address, such as a master that `MASTER_SERVER` named by its address, is never removed this way. See the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/master/opendj-packages/opendj-docker/README.md#replication[Replication section of the README of the image, window=\_blank]. +====== + [#repl-quick-setup] === Replication Quick Setup diff --git a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc index f5e9f1e275..6d54a26798 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc @@ -42,6 +42,8 @@ This chapter covers installation of OpenDJ server software and includes the foll * xref:#install-msi["To Install With the Windows Installer (MSI)"] +* xref:#install-docker["To Run OpenDJ in Docker"] + * xref:#install-properties-file["To Install OpenDJ Directory Server With a Properties File"] * xref:#pdb-to-je["To Move Data from a PDB Backend to a JE Backend"] @@ -87,6 +89,8 @@ Cross-platform OpenDJ REST to LDAP gateway web archive -- + +OpenDJ directory server is also published as a Docker image, which brings its own Java environment. See xref:#install-docker["To Run OpenDJ in Docker"]. ++ . If you plan to install OpenDJ DSML gateway or OpenDJ REST to LDAP gateway, make sure you have an appropriate application server installed. + @@ -653,6 +657,52 @@ The service takes the display name `OpenDJ Server`; when a host already runs ano ==== +[#install-docker] +.To Run OpenDJ in Docker +==== +OpenDJ directory server is published as the Docker image `openidentityplatform/opendj` on Docker Hub, and as `ghcr.io/openidentityplatform/opendj/opendj`. The image brings its own Java environment. On the first start of a container, the image runs `setup` with settings taken from environment variables; later starts use the instance that is already there. + +The tags `latest` and `{opendj-version}` are built from `Dockerfile`, on Eclipse Temurin; the tags `alpine` and `{opendj-version}-alpine` from `Dockerfile-alpine`. This procedure covers the first start only. The environment variables of the image, its health check, replication and certificates are described in the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/master/opendj-packages/opendj-docker/README.md[README of the image, window=\_blank]. + +. Start a container, with a volume for the instance: ++ + +[source, console] +---- +$ docker run -d --name opendj --init \ + -p 127.0.0.1:1389:1389 -p 127.0.0.1:1636:1636 -p 127.0.0.1:4444:4444 \ + -e ROOT_PASSWORD=password -e ADD_BASE_ENTRY=--addBaseEntry \ + -v opendj-data:/opt/opendj/data \ + openidentityplatform/opendj +---- ++ +The instance lives under `/opt/opendj/data`. The image declares no volume of its own, so mount one there: a container started without it keeps its instance in the container itself, and removing the container deletes the instance, while a container started again over the same volume serves the same data. The server runs as a non-root user and listens on ports above 1024: LDAP on 1389, LDAPS on 1636, and the administration connector on 4444. The example publishes these ports on the loopback interface of the host only; before you publish them on other interfaces, set a `ROOT_PASSWORD` of your own. The root user is `cn=Directory Manager`, with the password `ROOT_PASSWORD`, and the base DN is `dc=example,dc=com`; without `ADD_BASE_ENTRY` that suffix is created empty. The `--init` option puts a process in front of the server that reaps the processes left behind to it and passes `SIGTERM` on to it. + +. Wait until the container reports itself healthy; `docker inspect` reports `starting` until then: ++ + +[source, console] +---- +$ timeout 5m bash -c 'until [ "$(docker inspect -f "{{.State.Health.Status}}" opendj)" = healthy ]; do sleep 5; done' +---- ++ +On its first start the container starts the server, creates the backend, imports the data that `ADD_BASE_ENTRY` asked for, then stops the server and starts it again, so a client that only waits for the port may see its first requests fail. The container reports itself healthy once all of this has succeeded. A first start that fails never reports healthy: what failed is in `docker logs opendj`. + +. (Optional) Check that the server serves the base entry: ++ + +[source, console] +---- +$ docker exec opendj /opt/opendj/bin/ldapsearch --port 1389 \ + --bindDN "cn=Directory Manager" --bindPassword password \ + --baseDN dc=example,dc=com --searchScope base "(objectClass=*)" dn +dn: dc=example,dc=com +---- + +To stop the server, stop the container with `docker stop opendj`; `docker start opendj` starts it again. `docker stop` gives the server 10 seconds to shut down before it kills it: give a server with much data more time, for example with `docker stop -t 60 opendj`. + +==== + [#install-properties-file] .To Install OpenDJ Directory Server With a Properties File ==== diff --git a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-uninstall.adoc b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-uninstall.adoc index 1cff64e268..73c22560d2 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-uninstall.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-uninstall.adoc @@ -36,6 +36,8 @@ This chapter includes the following procedures: * xref:#uninstall-msi["To Uninstall the Windows MSI Package"] +* xref:#uninstall-docker["To Remove a Docker Container"] + [#uninstall-gui] .To Remove OpenDJ With the GUI Uninstaller @@ -185,3 +187,31 @@ Uninstalling removes the files installed by the package. Your configured instanc ==== +[#uninstall-docker] +.To Remove a Docker Container +==== +A container started from the Docker image with a volume mounted at `/opt/opendj/data`, as in xref:chap-install.adoc#install-docker["To Run OpenDJ in Docker"] in the __Installation Guide__, keeps its instance on that volume, which outlives the container. A container started without one keeps its instance in the container itself, and removing the container deletes it. + +. If the server replicates, stop replication on the server with `dsreplication disable` first, unless the containers of the topology run with `OPENDJ_REPLICATION_TYPE=simple` and `REPLICATION_PEERS`, and the server is registered in the topology by its name rather than by an address, as described in xref:../admin-guide/chap-replication.adoc#stop-repl-permanent["To Stop Replication Permanently For a Replica"] in the __Administration Guide__. + +. Stop and remove the container. This stops the server, but keeps its volume, if it has one: ++ + +[source, console] +---- +$ docker stop -t 60 opendj +$ docker rm opendj +---- + +. If the containers of the topology run with `OPENDJ_REPLICATION_TYPE=simple` and `REPLICATION_PEERS`, replace each remaining container with one started over the same volume with the same options, but with the removed server left out of `REPLICATION_PEERS`. The environment of a container cannot be changed, so restarting the container is not enough. On its start, each new container removes from the topology the servers registered by name that are not listed, and drops them from its own replication server lists, which are configuration of that server alone: replace every remaining container, or the ones you leave keep trying to reach the removed server. See the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/master/opendj-packages/opendj-docker/README.md#replication[Replication section of the README of the image, window=\_blank]. + +. To delete the data and the configuration of the server, remove its volume as well: ++ + +[source, console] +---- +$ docker volume rm opendj-data +---- + +==== + diff --git a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc index a8a038c5f3..db4aa0a949 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc @@ -47,6 +47,8 @@ This chapter includes the following procedures and examples: * xref:#upgrade-msi["To Upgrade the Windows MSI Installation"] +* xref:#upgrade-docker["To Upgrade a Docker Container"] + * xref:#upgrade-repl["To Upgrade Replicated Servers"] * xref:#new-repl-mixed-topology["To Add a New Replica to an Existing Topology"] @@ -298,6 +300,84 @@ C:\> net start "OpenDJ Server" ==== +[#upgrade-docker] +.To Upgrade a Docker Container +==== +A container started from a newer image over a volume that holds an instance of an older version upgrades that instance itself: before it starts the server, it runs `upgrade --no-prompt --force` on the volume. Upgrading the container therefore comes down to replacing it with one started from the newer image over the same volume. + +. Make sure the instance of the container is on a volume. ++ +The image declares no volume of its own: a container started without a volume mounted at `/opt/opendj/data` keeps its instance in the container itself, and removing the container deletes the instance. The following command lists the volumes of the container; the instance is on a volume if one of them is mounted at `/opt/opendj/data`: ++ + +[source, console] +---- +$ docker inspect -f '{{range .Mounts}}{{.Name}} {{.Destination}}{{println}}{{end}}' opendj +opendj-data /opt/opendj/data +---- ++ +If it is not, stop the container and copy its instance to a new volume, here `opendj-data`, which the following steps then use: ++ + +[source, console] +---- +$ docker stop -t 60 opendj +$ docker cp opendj:/opt/opendj/data/. - | \ + docker run --rm -i -v opendj-data:/data alpine tar -x -C /data +---- + +. Stop the container, and back up its volume. ++ +As described in xref:#before-you-upgrade["Before You Upgrade"], back up the files of the stopped instance rather than creating a backup archive with the `backup` command. `docker stop` gives the server 10 seconds to shut down before it kills it, so give a server with much data more time. The following example writes the volume `opendj-data` to an archive in the current directory. The archive holds the private keys of the server and the password hashes of its users, so only the administrators of the server may be able to read it: ++ + +[source, console] +---- +$ docker stop -t 60 opendj +$ docker run --rm -v opendj-data:/data -v "$PWD":/backup alpine \ + sh -c 'umask 077 && tar -czf /backup/opendj-data.tar.gz -C /data .' +---- + +. Remove the container, and start a new one from the newer image over the same volume, with every other option of the old container: its environment variables, and for a replicated container its `--hostname` and replication variables as well. In the following example, the old container was started as in xref:chap-install.adoc#install-docker["To Run OpenDJ in Docker"]: ++ + +[source, console, subs="+attributes"] +---- +$ docker rm opendj +$ docker run -d --name opendj --init \ + -p 127.0.0.1:1389:1389 -p 127.0.0.1:1636:1636 -p 127.0.0.1:4444:4444 \ + -e ROOT_PASSWORD=password -e ADD_BASE_ENTRY=--addBaseEntry \ + -v opendj-data:/opt/opendj/data \ + openidentityplatform/opendj:{opendj-version} +---- ++ +Images before 5.2.0 ran their health check bound as the root user, while the current image searches the root DSE anonymously. An instance that rejects unauthenticated requests (`reject-unauthenticated-requests:true`) answers that search with an error, and its container never reports healthy although the server serves. For such an instance, also mount a file holding the password of an account the health check may bind as, and set `HEALTHCHECK_BIND_DN` and `HEALTHCHECK_BIND_PASSWORD_FILE` on the new container, as described in the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/master/opendj-packages/opendj-docker/README.md#health-check[Health check section of the README of the image, window=\_blank]. + +. Wait until the container reports itself healthy: ++ + +[source, console] +---- +$ timeout 5m bash -c 'until [ "$(docker inspect -f "{{.State.Health.Status}}" opendj)" = healthy ]; do sleep 5; done' +---- ++ +The upgrade tasks that take long, such as verifying or rebuilding indexes, are performed before the server starts, since nobody is there to run them afterwards. On a large instance they can take longer than the start period of the health check, so the container may report `unhealthy` until the upgrade is over, and the command above may give up before: `docker logs opendj` shows which task is running, and the command can be run again. A container whose upgrade fails never reports healthy, and `docker logs opendj` shows why. + +To revert, remove the new container, replace the volume with one restored from the backup, and start a container from the older image over it, with the options of the old container. Restore into an empty volume: files that the upgrade added would be left behind in a volume that the archive is extracted over. + +[source, console] +---- +$ docker stop -t 60 opendj +$ docker rm opendj +$ docker volume rm opendj-data +$ docker run --rm -v opendj-data:/data -v "$PWD":/backup alpine \ + tar -xzf /backup/opendj-data.tar.gz -C /data +---- + +To upgrade replicated containers, upgrade one container at a time, and wait until it reports itself healthy before you go on to the next one, as described in xref:#upgrade-repl["To Upgrade Replicated Servers"]. + +==== + [#upgrade-dn-parsing] .To Check Stored DNs When Upgrading From a Release Before 5.2.0 ==== @@ -305,7 +385,7 @@ Before 5.2.0, the server read a DN only up to the first `;`, up to the end of a . A value with DN syntax that a client wrote with `;`, such as `member: cn=a;dc=example,dc=com`, was indexed under the key of `cn=a`. It now reads as `cn=a,dc=example,dc=com`, so an indexed equality search for that DN misses the entry until the index is rebuilt. The same holds for a value that was stored while its syntax was not enforced, and that only now parses. + -The `upgrade` command therefore offers to verify the equality indexes of the attributes that hold DNs, such as `member`, `uniqueMember`, `owner` or `seeAlso`, in every enabled backend at the end of the upgrade, and rebuilds them under each base DN where they do not match the entries. The verification reads every entry of these backends, so on a large backend it takes a while; the indexes are only rebuilt where it finds a missing key. The default answer is yes, so `upgrade --no-prompt` performs the verification too, as do the Docker image and the native packages, which run `upgrade --no-prompt --force`. If you declined it, run `verify-index` on these indexes with the server stopped, and rebuild them where it reports errors, as described in xref:../admin-guide/chap-indexing.adoc#rebuild-index["Rebuilding Indexes"] in the __Administration Guide__. Do the same for a backend that the upgrade could not read, such as a JDBC or Cassandra backend whose database was unreachable: the upgrade then warns, names the indexes and the base DN, and goes on, leaving these indexes as they were. A rebuild that the upgrade started and that fails, for instance because the temporary directory is full, fails the upgrade, as the index rebuilds of other upgrade tasks do: such indexes may be left untrusted, so that searches cannot use them, until they are rebuilt. The upgrade then neither verifies nor rebuilds the indexes of the base DNs that come after, as the same cause would most likely make their rebuild fail too: it names them, and you verify them and rebuild them where needed once the cause is fixed. +The `upgrade` command therefore offers to verify the equality indexes of the attributes that hold DNs, such as `member`, `uniqueMember`, `owner` or `seeAlso`, in every enabled backend at the end of the upgrade, and rebuilds them under each base DN where they do not match the entries. The verification reads every entry of these backends, so on a large backend it takes a while; the indexes are only rebuilt where it finds a missing key. The default answer is yes, so `upgrade --no-prompt` performs the verification too, as do the Docker image (see xref:#upgrade-docker["To Upgrade a Docker Container"]) and the native packages, which run `upgrade --no-prompt --force`. If you declined it, run `verify-index` on these indexes with the server stopped, and rebuild them where it reports errors, as described in xref:../admin-guide/chap-indexing.adoc#rebuild-index["Rebuilding Indexes"] in the __Administration Guide__. Do the same for a backend that the upgrade could not read, such as a JDBC or Cassandra backend whose database was unreachable: the upgrade then warns, names the indexes and the base DN, and goes on, leaving these indexes as they were. A rebuild that the upgrade started and that fails, for instance because the temporary directory is full, fails the upgrade, as the index rebuilds of other upgrade tasks do: such indexes may be left untrusted, so that searches cannot use them, until they are rebuilt. The upgrade then neither verifies nor rebuilds the indexes of the base DNs that come after, as the same cause would most likely make their rebuild fail too: it names them, and you verify them and rebuild them where needed once the cause is fixed. + A stored DN value with other content after an RDN, such as `cn="a"x,dc=example,dc=com`, no longer parses: replace it with the DN that was meant. diff --git a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/preface.adoc b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/preface.adoc index 3145d33a73..823010519e 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/preface.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/preface.adoc @@ -12,7 +12,7 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2017 ForgeRock AS. - Portions Copyright 2024 3A Systems LLC. + Portions Copyright 2024-2026 3A Systems LLC. //// :figure-caption!: @@ -26,7 +26,7 @@ This guide shows you how to install, upgrade, and remove OpenDJ software. -If you only want to try OpenDJ server software, and you do not plan to store any real or important data that you want to keep, then you need not read this entire guide. Instead read xref:chap-install.adoc#before-you-install["To Prepare For Installation"] and xref:chap-install.adoc#gui-install["To Install OpenDJ Directory Server With the GUI"]. +If you only want to try OpenDJ server software, and you do not plan to store any real or important data that you want to keep, then you need not read this entire guide. Instead read xref:chap-install.adoc#before-you-install["To Prepare For Installation"] and xref:chap-install.adoc#gui-install["To Install OpenDJ Directory Server With the GUI"]. Where Docker is available, xref:chap-install.adoc#install-docker["To Run OpenDJ in Docker"] starts a server with a single command. [#d67379e160] === Who Should Read this Guide From c0c948e21fda010a3169e2e3ed97d6c70ed7c56a Mon Sep 17 00:00:00 2001 From: Valera V Harseko Date: Thu, 8 Oct 2026 21:05:32 +0300 Subject: [PATCH 2/3] Say that ROOT_PASSWORD only sets the initial root password, what to do after a failed first start, and which volume the Docker upgrade backs up The Docker image reads ROOT_PASSWORD only when it creates the instance, and a container started over the volume of a failed first start can report itself healthy without the backend (#1182), so the install procedure says to remove that volume before trying again. The upgrade procedure uses the volume name that its first step prints, and backs up a bind mount as a host directory instead of archiving a fresh empty volume. --- .../main/asciidoc/install-guide/chap-install.adoc | 4 ++-- .../main/asciidoc/install-guide/chap-upgrade.adoc | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc index 6d54a26798..17a027587c 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc @@ -676,7 +676,7 @@ $ docker run -d --name opendj --init \ openidentityplatform/opendj ---- + -The instance lives under `/opt/opendj/data`. The image declares no volume of its own, so mount one there: a container started without it keeps its instance in the container itself, and removing the container deletes the instance, while a container started again over the same volume serves the same data. The server runs as a non-root user and listens on ports above 1024: LDAP on 1389, LDAPS on 1636, and the administration connector on 4444. The example publishes these ports on the loopback interface of the host only; before you publish them on other interfaces, set a `ROOT_PASSWORD` of your own. The root user is `cn=Directory Manager`, with the password `ROOT_PASSWORD`, and the base DN is `dc=example,dc=com`; without `ADD_BASE_ENTRY` that suffix is created empty. The `--init` option puts a process in front of the server that reaps the processes left behind to it and passes `SIGTERM` on to it. +The instance lives under `/opt/opendj/data`. The image declares no volume of its own, so mount one there: a container started without it keeps its instance in the container itself, and removing the container deletes the instance, while a container started again over the same volume serves the same data. The server runs as a non-root user and listens on ports above 1024: LDAP on 1389, LDAPS on 1636, and the administration connector on 4444. The example publishes these ports on the loopback interface of the host only; before you publish them on other interfaces, set a `ROOT_PASSWORD` of your own on the first start. The image reads `ROOT_PASSWORD` only when it creates the instance: a container started over an instance that is already there keeps the root password of that instance, which you change with `ldappasswordmodify` as on any other server. A replicated container binds with `ROOT_PASSWORD` to join its topology on every start, so read the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/master/opendj-packages/opendj-docker/README.md#replication[Replication section of the README of the image, window=\_blank] before you change the root password of one. The root user is `cn=Directory Manager`, with the initial password `ROOT_PASSWORD`, and the base DN is `dc=example,dc=com`; without `ADD_BASE_ENTRY` that suffix is created empty. The `--init` option puts a process in front of the server that reaps the processes left behind to it and passes `SIGTERM` on to it. . Wait until the container reports itself healthy; `docker inspect` reports `starting` until then: + @@ -686,7 +686,7 @@ The instance lives under `/opt/opendj/data`. The image declares no volume of its $ timeout 5m bash -c 'until [ "$(docker inspect -f "{{.State.Health.Status}}" opendj)" = healthy ]; do sleep 5; done' ---- + -On its first start the container starts the server, creates the backend, imports the data that `ADD_BASE_ENTRY` asked for, then stops the server and starts it again, so a client that only waits for the port may see its first requests fail. The container reports itself healthy once all of this has succeeded. A first start that fails never reports healthy: what failed is in `docker logs opendj`. +On its first start the container starts the server, creates the backend, imports the data that `ADD_BASE_ENTRY` asked for, then stops the server and starts it again, so a client that only waits for the port may see its first requests fail. The container reports itself healthy once all of this has succeeded. A first start that fails never reports healthy: what failed is in `docker logs opendj`. To try again, remove the container and its volume, with `docker rm -f opendj` and `docker volume rm opendj-data`, then start over: a container started over the volume of a failed first start takes it for an installed instance, and can report itself healthy without the backend or the base entry. . (Optional) Check that the server serves the base entry: + diff --git a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc index db4aa0a949..0e7002cabd 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc @@ -316,7 +316,15 @@ $ docker inspect -f '{{range .Mounts}}{{.Name}} {{.Destination}}{{println}}{{end opendj-data /opt/opendj/data ---- + -If it is not, stop the container and copy its instance to a new volume, here `opendj-data`, which the following steps then use: +The following steps use the volume `opendj-data`: use the name that the command printed instead. An empty name is a bind mount of a host directory, which the following command shows; back up that directory instead of running the commands of the next step, and mount it again in step 3: ++ + +[source, console] +---- +$ docker inspect -f '{{range .Mounts}}{{.Source}} {{.Destination}}{{println}}{{end}}' opendj +---- ++ +If nothing is mounted at `/opt/opendj/data`, stop the container and copy its instance to a new volume, here `opendj-data`, which the following steps then use: + [source, console] @@ -328,7 +336,7 @@ $ docker cp opendj:/opt/opendj/data/. - | \ . Stop the container, and back up its volume. + -As described in xref:#before-you-upgrade["Before You Upgrade"], back up the files of the stopped instance rather than creating a backup archive with the `backup` command. `docker stop` gives the server 10 seconds to shut down before it kills it, so give a server with much data more time. The following example writes the volume `opendj-data` to an archive in the current directory. The archive holds the private keys of the server and the password hashes of its users, so only the administrators of the server may be able to read it: +As described in xref:#before-you-upgrade["Before You Upgrade"], back up the files of the stopped instance rather than creating a backup archive with the `backup` command. `docker stop` gives the server 10 seconds to shut down before it kills it, so give a server with much data more time. The following example writes the volume `opendj-data` to an archive in the current directory. The archive holds the private keys of the server and the password hashes of its users, so make sure that only the administrators of the server can read it: + [source, console] From 6510d4e680a98dc8727ddc3b9138b03066d902c4 Mon Sep 17 00:00:00 2001 From: Valera V Harseko Date: Fri, 9 Oct 2026 10:31:56 +0300 Subject: [PATCH 3/3] Say when the Docker image reads ROOT_PASSWORD on every start, not to restart a container past a failed upgrade, and to stop the container before backing up a bind mount --- .../src/main/asciidoc/install-guide/chap-install.adoc | 6 +++--- .../src/main/asciidoc/install-guide/chap-upgrade.adoc | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc index 17a027587c..7a7ab55a9a 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-install.adoc @@ -676,9 +676,9 @@ $ docker run -d --name opendj --init \ openidentityplatform/opendj ---- + -The instance lives under `/opt/opendj/data`. The image declares no volume of its own, so mount one there: a container started without it keeps its instance in the container itself, and removing the container deletes the instance, while a container started again over the same volume serves the same data. The server runs as a non-root user and listens on ports above 1024: LDAP on 1389, LDAPS on 1636, and the administration connector on 4444. The example publishes these ports on the loopback interface of the host only; before you publish them on other interfaces, set a `ROOT_PASSWORD` of your own on the first start. The image reads `ROOT_PASSWORD` only when it creates the instance: a container started over an instance that is already there keeps the root password of that instance, which you change with `ldappasswordmodify` as on any other server. A replicated container binds with `ROOT_PASSWORD` to join its topology on every start, so read the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/master/opendj-packages/opendj-docker/README.md#replication[Replication section of the README of the image, window=\_blank] before you change the root password of one. The root user is `cn=Directory Manager`, with the initial password `ROOT_PASSWORD`, and the base DN is `dc=example,dc=com`; without `ADD_BASE_ENTRY` that suffix is created empty. The `--init` option puts a process in front of the server that reaps the processes left behind to it and passes `SIGTERM` on to it. +The instance lives under `/opt/opendj/data`. The image declares no volume of its own, so mount one there: a container started without it keeps its instance in the container itself, and removing the container deletes the instance, while a container started again over the same volume serves the same data. The server runs as a non-root user and listens on ports above 1024: LDAP on 1389, LDAPS on 1636, and the administration connector on 4444. The example publishes these ports on the loopback interface of the host only; before you publish them on other interfaces, set a `ROOT_PASSWORD` of your own on the first start. Apart from the replication join described next, the image reads `ROOT_PASSWORD` only when it creates the instance: a container started over an instance that is already there keeps the root password of that instance, which you change with `ldappasswordmodify` as on any other server. A container replicated with `OPENDJ_REPLICATION_TYPE=simple` binds with `ROOT_PASSWORD` to join its topology on every start, so read the link:https://github.com/OpenIdentityPlatform/OpenDJ/blob/master/opendj-packages/opendj-docker/README.md#replication[Replication section of the README of the image, window=\_blank] before you change the root password of one. The root user is `cn=Directory Manager`, with the initial password `ROOT_PASSWORD`, and the base DN is `dc=example,dc=com`; without `ADD_BASE_ENTRY` that suffix is created empty. The `--init` option puts a process in front of the server that reaps the processes left behind to it and passes `SIGTERM` on to it. -. Wait until the container reports itself healthy; `docker inspect` reports `starting` until then: +. Wait until the container reports itself healthy; `docker inspect` reports `starting` until then, and `unhealthy` once the 5-minute start period is over while the checks still fail: + [source, console] @@ -686,7 +686,7 @@ The instance lives under `/opt/opendj/data`. The image declares no volume of its $ timeout 5m bash -c 'until [ "$(docker inspect -f "{{.State.Health.Status}}" opendj)" = healthy ]; do sleep 5; done' ---- + -On its first start the container starts the server, creates the backend, imports the data that `ADD_BASE_ENTRY` asked for, then stops the server and starts it again, so a client that only waits for the port may see its first requests fail. The container reports itself healthy once all of this has succeeded. A first start that fails never reports healthy: what failed is in `docker logs opendj`. To try again, remove the container and its volume, with `docker rm -f opendj` and `docker volume rm opendj-data`, then start over: a container started over the volume of a failed first start takes it for an installed instance, and can report itself healthy without the backend or the base entry. +On its first start the container starts the server, creates the backend, imports the data that `ADD_BASE_ENTRY` asked for, then stops the server and starts it again, so a client that only waits for the port may see its first requests fail. The container reports itself healthy once all of this has succeeded. A first start that fails never reports healthy: what failed is in `docker logs opendj`. To try again, remove the container and its volume, with `docker rm -f opendj` and `docker volume rm opendj-data`, then start over: a container started over the volume of a failed first start can take it for an installed instance and report itself healthy without the backend or the base entry. . (Optional) Check that the server serves the base entry: + diff --git a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc index 0e7002cabd..9ee5239f23 100644 --- a/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc +++ b/opendj-doc-generated-ref/src/main/asciidoc/install-guide/chap-upgrade.adoc @@ -316,7 +316,7 @@ $ docker inspect -f '{{range .Mounts}}{{.Name}} {{.Destination}}{{println}}{{end opendj-data /opt/opendj/data ---- + -The following steps use the volume `opendj-data`: use the name that the command printed instead. An empty name is a bind mount of a host directory, which the following command shows; back up that directory instead of running the commands of the next step, and mount it again in step 3: +The following steps use the volume `opendj-data`: use the name that the command printed instead. An empty name is a bind mount of a host directory, which the following command shows. In the next step, stop the container with its first command, then back up that directory instead of running the second one, and mount the directory again in step 3: + [source, console] @@ -369,7 +369,7 @@ Images before 5.2.0 ran their health check bound as the root user, while the cur $ timeout 5m bash -c 'until [ "$(docker inspect -f "{{.State.Health.Status}}" opendj)" = healthy ]; do sleep 5; done' ---- + -The upgrade tasks that take long, such as verifying or rebuilding indexes, are performed before the server starts, since nobody is there to run them afterwards. On a large instance they can take longer than the start period of the health check, so the container may report `unhealthy` until the upgrade is over, and the command above may give up before: `docker logs opendj` shows which task is running, and the command can be run again. A container whose upgrade fails never reports healthy, and `docker logs opendj` shows why. +The upgrade tasks that take long, such as verifying or rebuilding indexes, are performed before the server starts, since nobody is there to run them afterwards. On a large instance they can take longer than the start period of the health check, so the container may report `unhealthy` until the upgrade is over, and the command above may give up before: `docker logs opendj` shows which task is running, and the command can be run again. A container whose upgrade fails does not report itself healthy: `docker logs opendj` shows why, and the upgrade log `/opt/opendj/data/logs/upgrade.log` has the details. Do not start it again to get past the failure: when a task that runs after the upgrade fails, such as an index rebuild, the new version is already recorded, so the next start skips the upgrade and reports healthy with the indexes as the failed rebuild left them, and without the tasks that were to follow it. Revert as follows, or rebuild the indexes that `docker logs opendj` names before you rely on the container. To revert, remove the new container, replace the volume with one restored from the backup, and start a container from the older image over it, with the options of the old container. Restore into an empty volume: files that the upgrade added would be left behind in a volume that the archive is extracted over.