IT Toolbox
Menu
HomeProceduresRecover a Docker service stuck in a restart loop
Procedure

Recover a Docker service stuck in a restart loop

Diagnose a Docker restart loop using logs, exit state, memory and dependency evidence while preserving volumes and the deployment configuration.

TopicProcedures → About 6 min read

Objective

Diagnose a Docker Engine container that repeatedly exits on a Linux host, preserve its data and evidence, then correct the cause before restoring automatic restarts. Compose and orchestrated services require their own deployment controls.

  • Keep persistent volumes and the original deployment configuration.
  • Do not use repeated restarts as the only diagnostic action.
  • Separate observation commands from service-changing commands, and retain the previous restart policy.

Prerequisites

  • Exact container identity, incident time and Docker Engine access on the affected Linux host.
  • Original Compose or deployment configuration and knowledge of persistent mounts and dependencies.
  • Permission for the service interruption and a known recovery option for the workload.
  • Protected storage for diagnostic exports; getent, nc and kernel-log access depend on the host.

Step-by-step procedure

Establish the baseline and scope

Record the affected container, image, incident time and recent deployment changes. Save its current state and restart policy before stopping it. Compare with a known working deployment where available.

  • The identity or workload, timing and intended result are recorded.

Capture state and deployment configuration

Identify the exact container and the deployment source before changing it. Capture state, image reference, restart count, restart policy and mounted-data locations; compare them with the intended Compose or deployment configuration. Environment inspection may reveal credentials, so restrict saved output and redact values before sharing it. Keep persistent volumes while investigating.

  • The failing container, deployment source and persistent-data locations are known; configuration evidence is retained safely.

Read the first relevant failure

Use timestamps and a bounded log window around the first observed failure. Follow the earliest application error rather than only the final restart message. If the application writes to a mounted file or another logging destination, collect the relevant output there as well; empty docker logs output does not prove that startup was healthy.

  • The first useful error and its timestamp are captured, or the missing logging path is identified.

Interpret the exit state

Inspect ExitCode, Error, StartedAt and FinishedAt with the application logs and deployment events. Exit code 137 indicates a SIGKILL result and is not proof of an out-of-memory event on its own; correlate it with OOMKilled and host evidence. Check the entrypoint, command, permissions and required configuration when the application exits immediately.

  • The exit status is linked to supporting evidence instead of being treated as a complete diagnosis.

Correlate memory and storage evidence

Check OOMKilled, host kernel messages and the configured memory limit at the incident time. Also verify free space for application data and logs. A memory limit increase should follow an assessment of workload and host capacity; it may only postpone a leak. An empty or inaccessible kernel log leaves the memory cause unconfirmed.

  • Memory or storage pressure is supported by incident-time evidence, or explicitly remains unconfirmed.

Test the required dependency path

Check the configured DNS name, destination port, certificate and application credentials for dependencies such as a database or API. A successful host-side DNS or TCP check does not establish that the container’s network and application authentication work. Repeat the relevant test from the intended network context where possible without modifying persistent data.

  • The evidence distinguishes name resolution, connectivity and application-level access to the dependency.

Pause the loop deliberately

Record the existing policy and arrange the allowed interruption before stopping the affected container. A temporary no-restart policy can help observe one attempt; it does not fix the application fault. For Compose or an orchestrator, use its deployment source and lifecycle controls rather than relying on a manual change that the next deployment will replace.

  • The loop is controlled for investigation, and the previous policy and persistent data remain available.

Apply the fix and validate one restart

Correct the demonstrated cause in the versioned deployment configuration, image or secret source. Start only the intended workload and observe its first attempt and logs. Once the application test succeeds, restore the approved restart policy and monitor status and RestartCount over the agreed observation period. A running process alone does not establish that the service works.

  • The application works, restart count is stable and the correction survives the next intended deployment.

Validate the complete service

Complete the validation checklist below and retain the observed results. Record unresolved checks instead of treating a command success as a complete service recovery.

  • The outcome is checked against the service-specific criteria below.

Command examples and their effects

These examples target Docker Engine on Linux, not a Swarm service. Replace the quoted CONTAINER_NAME, DEPENDENCY_NAME and PORT_NUMBER tokens with the intended values. Run observations first; policy updates, stop and start change the service. Preserve the previous policy and use the deployment source for Compose-managed workloads. Do not share raw environment exports containing secrets.

List container status

docker ps -a --no-trunc

Observe the selected container state

docker inspect 'CONTAINER_NAME' --format '{{json .State}}'

Record the current restart policy

docker inspect 'CONTAINER_NAME' --format '{{json .HostConfig.RestartPolicy}}'

Read timestamped recent logs

docker logs --timestamps --tail 200 'CONTAINER_NAME'

Read the incident log window

docker logs --since 30m 'CONTAINER_NAME'

Service-changing action: temporarily disable automatic restarts

docker update --restart=no 'CONTAINER_NAME'

Service-changing action: stop the affected container

docker stop 'CONTAINER_NAME'

Observe OOM, exit code and error fields

docker inspect 'CONTAINER_NAME' --format 'OOM={{.State.OOMKilled}} Exit={{.State.ExitCode}} Error={{.State.Error}}'

Read relevant Linux kernel messages where permitted

dmesg -T | grep -i -E 'oom|killed process' | tail -30

Check filesystem capacity

df -h

Observe persistent mounts

docker inspect 'CONTAINER_NAME' --format '{{json .Mounts}}'

Sensitive output: inspect environment locally and redact secrets

docker inspect 'CONTAINER_NAME' --format '{{json .Config.Env}}'

Check dependency name resolution from the host

getent hosts 'DEPENDENCY_NAME'

Check dependency TCP reachability from the host

nc -vz 'DEPENDENCY_NAME' 'PORT_NUMBER'

Service-changing action: start one attempt after the targeted fix

docker start 'CONTAINER_NAME'

Follow output; use Ctrl+C to stop following logs

docker logs -f 'CONTAINER_NAME'

Service-changing example only: use unless-stopped only if it is the approved policy

docker update --restart=unless-stopped 'CONTAINER_NAME'

Observe restart count and status

docker inspect 'CONTAINER_NAME' --format 'Restarts={{.RestartCount}} Status={{.State.Status}}'

Validation

The procedure is validated when:

  • The intended application workflow succeeds and RestartCount stays stable during the observation period.
  • The initial fault and the corrective change have supporting evidence.
  • The fix is present in the deployment source, with required data, dependencies and resources available.

Rollback

  • Return to the last known working image or deployment configuration when the targeted fix fails.
  • Keep the persistent volumes; do not prune or delete them to recreate the container.
  • Restore the recorded restart policy only when doing so will not recreate an uncontrolled loop; otherwise keep the affected workload stopped pending recovery.

Troubleshooting / common errors

  • Exit 137 without matching OOM evidence: check for other SIGKILL causes and deployment actions.
  • No container logs: inspect the logging configuration, entrypoint and application log location.
  • Host checks succeed but the container fails: compare network context, mounts and deployment environment.
  • RestartCount still rises: verify that the changed container and deployed configuration are the ones serving the workload.

Official references

Keep the selected scope, evidence and outcome with the procedure record. Use the official references for the installed product and version.

Support the development of BAOI Hosting, domains and new IT resources.
❤️ Support BAOI

My favorites