Cloud Native 16 min read

Running Business Containers as Non-Root: Practical Guide and Real-World Scripts

This article explains why running business containers without root privileges is essential for security, outlines the necessary background and risks, and provides detailed step‑by‑step methods, Dockerfile snippets, entrypoint scripts, and real‑world examples for MySQL, Redis, CoreDNS, Consul, and cAdvisor to achieve safe non‑root container deployments.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Running Business Containers as Non-Root: Practical Guide and Real-World Scripts

Background

Customer security requirements demand that business containers run without root privileges. Many containers need to manipulate ipset, iptables, and other system resources, which cannot be solved by plain rootless Docker; therefore existing images must be modified so that all processes inside run as non‑root.

Prerequisites

Why root is unsafe

Although Linux provides user namespaces, Docker does not support per‑container UID mappings like Podman, and containers can still modify mounted filesystems. A careless rm -rf /* in an Alpine container would delete the entire host filesystem.

docker run --rm -v /mnt/sda1:/mnt/sda1 -it alpine
cp /mnt/sda1/somefile.tar.gz .
 tar xzvf somefile.tar.gz
 cd somefile-v1.0
 # inspect contents, then
 cd ..
 rm -rf *

Choosing USER vs entrypoint script

For simple processes (exporters, HTTP APIs) you can set USER in the Dockerfile or use -u user:group at run time. Examples include:

danielqsj/kafka_exporter

ClickHouse/clickhouse_exporter

kubernetes addonresizer

For containers that persist data (MySQL, Redis) you must adjust directory ownership before the container starts, because the UID/GID inside the container differs from the host.

Mount with -v or Docker volume

Use hostPath in Kubernetes

Fixed PV

PVC in a storage class

Deploy to another Kubernetes cluster

Practical Cases

MySQL

The official MySQL image creates a dedicated mysql user and starts with ENTRYPOINT CMD. Example entrypoint: docker-entrypoint.sh mysqld You can also change the listening port via command line, e.g. docker run ... mysql:5.7 --port 4306.

Redis

Example startup script that switches to a non‑root user with gosu (or su‑exec on Alpine) and fixes permissions.

#!/bin/sh
set -e
if [ "${1#-}" != "$1" ] || [ "${1%.conf}" != "$1" ]; then
  set -- redis-server "$@"
fi
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
  find . \! -user redis -exec chown redis '{}' +
  exec gosu redis "$0" "$@"
fi
# set appropriate umask
um=$(umask)
if [ "$um" = '0022' ]; then
  umask 0077
fi
exec "$@"

CoreDNS

CoreDNS 1.11.0 supports non‑root, but the project uses 1.10.1. A custom Dockerfile rebuilds the binary, sets the capability cap_net_bind_service=+ep, and runs as nonroot:

ARG DEBIAN_IMAGE=debian:stable-slim
ARG BASE=gcr.io/distroless/static-debian12:nonroot
FROM coredns/coredns:1.10.1 as bin
FROM ${DEBIAN_IMAGE} AS build
SHELL ["/bin/sh", "-ec"]
RUN export DEBCONF_NONINTERACTIVE_SEEN=true \
    DEBIAN_FRONTEND=noninteractive \
    DEBIAN_PRIORITY=critical TERM=linux ; \
    apt-get -qq update ; \
    apt-get -yyqq upgrade ; \
    apt-get -yyqq install ca-certificates libcap2-bin ; \
    apt-get clean
COPY --from=bin /coredns /coredns
RUN setcap cap_net_bind_service=+ep /coredns
FROM ${BASE}
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /coredns /coredns
USER nonroot:nonroot
EXPOSE 53 53/udp
ENTRYPOINT ["/coredns"]

Building must use BuildKit (e.g.

DOCKER_BUILDKIT=1 docker build --platform=amd64 . -t coredns/coredns:1.10.1 --load

) otherwise the capability is lost.

Consul

Modify the official entrypoint to use recursive chown and drop dumb‑init so that PID 1 runs as non‑root:

FROM consul:${VER}
RUN sed -ri -e 's/(chown)(\s+consul:)/\1 -R\2/' \
    -e '1s@/usr/bin/dumb-init\s+@@' /usr/local/bin/docker-entrypoint.sh

cAdvisor

To run cAdvisor without root, add a custom entrypoint that changes ownership of the Docker socket, adds the non‑root user to the socket’s group, and then executes cAdvisor with su‑exec or gosu:

#!/bin/sh
set -e
[ -z "$D_SOCK" ] && D_SOCK=/var/run/docker.sock
if [ "${1:0:1}" = '-' ]; then
  set -- cadvisor "$@"
fi
if [ "$1" = 'cadvisor' ]; then
  if [ "$(id -u)" = '0' -a -n "$RUN_USER" ]; then
    if [ -S "$D_SOCK" ]; then
      group_id=$(stat -c "%g" "$D_SOCK")
      if ! getent group | cut -d: -f3 | grep -wq $group_id; then
        addgroup -g $group_id docker
      fi
      group_name=$(stat -c "%G" "$D_SOCK")
      if ! id -nG $RUN_USER | grep -w $group_name; then
        adduser $RUN_USER $group_name
      fi
    fi
    exec su-exec $RUN_USER "$@"
  fi
fi
exec "$@"

Additional notes

Place pid and socket files under /tmp.

Grant write permission to /dev/std* if the business process needs it (e.g., chmod a+w /dev/std*).

Keep consistent uid:gid across custom images and official images to avoid permission problems on mounted data directories.

Avoid chmod -R 777 on data directories.

Non‑root processes cannot bind ports below 1024 without capabilities; use setcap for services like CoreDNS.

When mounting /var/run/docker.sock, ensure the non‑root user belongs to the socket’s group (often GID 660).

Cron cannot run as non‑root; use go-crond as an alternative.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

KubernetesContainer SecurityCoreDNSNon-rootENTRYPOINTgosu
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.