Skip to content

Docker image: a freshly bootstrapped container ignores SIGTERM and is killed without stopping the server #1085

Description

@vharseko

Problem

On the first start of a container (empty data volume), run.sh does not exec the server. Setup has already started OpenDJ in the background, so the script ends with (run.sh#L97-L102):

# Opendj is probably already started in detach mode at the install
if (bin/status -n | grep Started); then
  echo "OpenDJ is started"

  # Use tail instead of sleep to allow the container to be stopped with SIGTERM
  tail -f /dev/null
fi

PID 1 of the container is then bash, which installs no handler for SIGTERM. The kernel does not deliver a signal without a handler to the init process of a PID namespace (pid_namespaces(7)), and tail never receives it. So docker stop / pod termination has no effect until the grace period runs out, and then everything is SIGKILLed. The server is never stopped cleanly: the JE environment is not closed, and nothing is flushed.

Measured with openidentityplatform/opendj:latest (2026-07-17):

start processes docker stop -t 20 exit code
first start (bootstrap) 1 bash, java, tail 20 s (the whole timeout) 137 (SIGKILL)
restart of the same container (./data/config exists, exec ./bin/start-ds --nodetach) 1 java 4 s 143 (SIGTERM handled)

On Kubernetes the first pod lifetime therefore always ends with a kill after terminationGracePeriodSeconds (30 s by default).

Expected

The container stops cleanly on SIGTERM whether or not it bootstrapped the instance. For example, after the bootstrap stop the server that setup started (bin/stop-ds) and exec ./bin/start-ds --nodetach, as the restart branch already does, so the server becomes PID 1 in both cases. (A trap 'bin/stop-ds' TERM plus wait would also work, but it keeps two code paths.)

Notes

The comment above tail -f /dev/null states the opposite intent ("to allow the container to be stopped with SIGTERM"). It does not hold for PID 1.

Found while evaluating the Helm chart proposal (discussion #1079).

Prior art

The Wren:DS image, another community fork of the same code, does this already (docker-entrypoint.sh, bootstrap/setup.sh). On the first start it:

  1. runs setup --doNotStart;
  2. starts the server;
  3. applies its init scripts;
  4. stops the server;
  5. exec ./bin/start-ds --nodetach, on the first start and on every later one alike.

Gluu's image (gluufederation/opendj) also ends its entrypoint with exec /opt/opendj/bin/start-ds -N, and runs the replication join in the background next to it (#1086).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions