Docker
ps command
troubleshooting
container issues
Linux

ps command doesn't work in docker container

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

The ps command fails inside Docker containers because most minimal base images do not include the procps package. The fix is straightforward: install procps using your image's package manager. On Debian/Ubuntu, run apt-get install -y procps. On Alpine, run apk add procps. However, there are better alternatives for process inspection in containers, and understanding why ps is missing leads to smarter container design decisions.

Why ps Is Missing

Docker images are built to be small. Base images like alpine, distroless, scratch, and slim variants of debian or ubuntu strip out utilities that are not strictly required to run the application. The ps command is part of the procps package (or procps-ng on some distributions), and it is not considered essential for running containerized applications.

This is intentional. Smaller images provide:

BenefitImpact
Smaller attack surfaceFewer binaries means fewer potential vulnerability vectors
Faster pulls and deploysLess data to transfer over the network
Faster startupLess filesystem overhead during container initialization
Lower storage costsEspecially significant when running hundreds of containers

So while the missing ps command can be frustrating during debugging, it reflects a deliberate design trade-off.

Installing ps in the Dockerfile

The correct place to install procps is in the Dockerfile, not interactively inside a running container. Interactive installs are lost when the container stops.

Debian / Ubuntu

dockerfile
1FROM ubuntu:22.04
2
3RUN apt-get update && \
4    apt-get install -y --no-install-recommends procps && \
5    rm -rf /var/lib/apt/lists/*
6
7CMD ["bash"]

The --no-install-recommends flag avoids pulling in unnecessary packages. The rm -rf /var/lib/apt/lists/* line removes the package index cache, keeping the image small.

Alpine

dockerfile
1FROM alpine:3.19
2
3RUN apk add --no-cache procps
4
5CMD ["sh"]

The --no-cache flag avoids storing the package index locally, which saves space.

Amazon Linux / CentOS / RHEL

dockerfile
1FROM amazonlinux:2023
2
3RUN yum install -y procps-ng && \
4    yum clean all
5
6CMD ["bash"]

On these distributions, the package is called procps-ng rather than procps.

Package Names by Distribution

Base ImagePackage ManagerPackage NameInstall Command
Ubuntu / Debianaptprocpsapt-get install -y procps
Alpineapkprocpsapk add procps
Amazon Linux / CentOS / RHELyum/dnfprocps-ngyum install -y procps-ng
Fedoradnfprocps-ngdnf install -y procps-ng
Arch Linuxpacmanprocps-ngpacman -S procps-ng

Temporary Installation in a Running Container

For one-off debugging sessions, you can install procps inside a running container. This change is ephemeral and disappears when the container stops.

bash
1# For Debian/Ubuntu containers
2docker exec -it <container_id> bash -c "apt-get update && apt-get install -y procps"
3
4# For Alpine containers
5docker exec -it <container_id> sh -c "apk add procps"

After installation, ps works for the remainder of that container's lifetime.

Alternatives to ps Inside Containers

Before installing procps, consider whether you actually need it. Docker provides several external tools that give you process information without modifying the container.

docker top

bash
docker top <container_id>

This shows processes running inside the container, similar to ps, but executed from the host. No installation required inside the container.

bash
# With custom ps options
docker top <container_id> -o pid,user,%cpu,%mem,command

docker stats

bash
docker stats <container_id>

This provides real-time CPU, memory, network, and I/O statistics for running containers. It is more useful than ps for monitoring resource usage.

Reading /proc directly

The /proc filesystem is always available inside Linux containers, even without procps installed. You can extract process information manually:

bash
1# List all process IDs
2ls /proc/[0-9]*
3
4# Get the command line of PID 1
5cat /proc/1/cmdline | tr '\0' ' '
6
7# Get memory status of PID 1
8cat /proc/1/status | grep -i vmrss
9
10# List all processes with their command names
11for pid in /proc/[0-9]*; do
12    echo "$(basename $pid): $(cat $pid/comm 2>/dev/null)"
13done

This approach works on any Linux container without installing anything.

nsenter from the host

For containers that do not even have a shell, you can use nsenter from the host to enter the container's namespace and run ps from the host's binaries:

bash
1# Get the container's PID on the host
2docker inspect --format '{{.State.Pid}}' <container_id>
3
4# Enter the container's PID namespace and run ps
5nsenter -t <container_pid> -p -m ps aux

This is particularly useful for distroless or scratch-based containers where installing packages is not an option.

Debug Containers in Kubernetes

In Kubernetes environments, ephemeral debug containers provide a clean way to debug without modifying the target pod:

bash
kubectl debug -it <pod-name> --image=busybox --target=<container-name>

This attaches a debug container that shares the process namespace of the target container. You can install and run diagnostic tools without changing the application container's image.

Multi-Stage Builds: Keep Production Images Clean

If you need ps during development but not in production, use a multi-stage build:

dockerfile
1# Build stage with debugging tools
2FROM python:3.12-slim AS builder
3RUN apt-get update && apt-get install -y procps
4COPY . /app
5WORKDIR /app
6RUN pip install -r requirements.txt
7
8# Production stage without debugging tools
9FROM python:3.12-slim AS production
10COPY --from=builder /app /app
11WORKDIR /app
12CMD ["python", "main.py"]

The production image stays lean while the build stage has all the tools you need for debugging during development.

Alternatively, define separate Dockerfiles or build targets:

dockerfile
1FROM python:3.12-slim AS base
2COPY . /app
3WORKDIR /app
4RUN pip install -r requirements.txt
5CMD ["python", "main.py"]
6
7FROM base AS debug
8RUN apt-get update && \
9    apt-get install -y --no-install-recommends procps curl vim && \
10    rm -rf /var/lib/apt/lists/*
bash
1# Build production image
2docker build --target base -t myapp:prod .
3
4# Build debug image
5docker build --target debug -t myapp:debug .

Common Pitfalls

  • Installing packages interactively instead of in the Dockerfile. Interactive installs are lost when the container restarts. Always add package installations to the Dockerfile for persistence.
  • Not cleaning up package caches. Failing to run rm -rf /var/lib/apt/lists/* (Debian) or using --no-cache (Alpine) bloats the image layer with index data that is never used again.
  • Using the wrong package name. The package is procps on Debian and Alpine but procps-ng on CentOS, RHEL, Amazon Linux, and Fedora. Using the wrong name produces a "package not found" error.
  • Adding debug tools to production images. Every additional binary increases the attack surface. Use multi-stage builds to keep debug tools out of production.
  • Forgetting about docker top. Many developers install procps inside a container when docker top from the host would have answered their question without any modification.
  • Ignoring /proc. The proc filesystem is always available. For quick checks, reading /proc/1/cmdline or /proc/1/status is faster than installing a package.

Summary

  • The ps command is missing from Docker containers because minimal base images exclude the procps package to reduce image size and attack surface.
  • Install procps (or procps-ng) in your Dockerfile using the appropriate package manager for your base image.
  • For one-off debugging, install it interactively with docker exec, but this change is lost when the container stops.
  • Prefer external tools like docker top and docker stats when possible, as they require no changes to the container.
  • The /proc filesystem and nsenter provide process information without any package installation.
  • Use multi-stage builds to include debug tools in development images while keeping production images clean.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.