Run startup logic with a distroless Fluent Bit container

Choose a compatible shell, a debug image, or a Kubernetes init container for Fluent Bit startup tasks without relying on missing tools.

Best practices
Illustration of collecting, processing, and monitoring logs

A distroless Fluent Bit image has no shell to interpret a shell script. It includes the Fluent Bit executable and its required runtime files; it is not literally a container containing only one binary. An executable script still needs the interpreter named in its shebang.

There are three practical approaches. Choose according to whether the script must run inside Fluent Bit's container or only prepare its configuration.

Add an interpreter deliberately

A custom image can include a shell and an entrypoint script, but copying /bin/sh from an arbitrary BusyBox image is not sufficient evidence that it will run. The executable may require a dynamic loader or libraries absent from the destination. Architecture must also match.

If you supply a verified, statically linked BusyBox binary in your build context, the pattern is:

FROM cr.fluentbit.io/fluent/fluent-bit:4.2.3
COPY busybox /busybox
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT ["/busybox", "sh", "/entrypoint.sh"]

Make the binary executable before building. A minimal script finishes by replacing the shell with Fluent Bit:

#!/bin/sh
set -eu
# Perform initialization using commands actually present in the image.
exec /fluent-bit/bin/fluent-bit -c /fluent-bit/etc/fluent-bit.conf

BusyBox sh is not Bash. A script using Bash syntax needs Bash and its dependencies, or a rewrite for the available shell. Other commands in the script need their own binaries or explicit BusyBox applet calls.

Use an image with a shell

For development, Fluent Bit publishes versioned -debug images with a Debian shell and package manager. For example, use cr.fluentbit.io/fluent/fluent-bit:4.2.3-debug as the base and explicitly set the entrypoint to /bin/sh /entrypoint.sh.

A distribution image with a packaged Fluent Bit is another option, provided that package exists for the chosen release and architecture. Do not assume an Alpine installation matches a glibc-based build's plugins or parsing behavior. Pin and test the complete image. See the official image documentation.

Move preparation into an init container

For Kubernetes, an init container can prepare files in a shared volume before Fluent Bit starts. This Pod-spec fragment creates a small configuration without needing a shell in the main container:

volumes:
  - name: shared
    emptyDir: {}
initContainers:
  - name: init-config
    image: busybox:1.37
    command: ["sh", "-c"]
    args:
      - printf '[INPUT]\n    Name dummy\n[OUTPUT]\n    Name stdout\n    Match *\n' > /shared/fluent-bit.conf
    volumeMounts:
      - name: shared
        mountPath: /shared
containers:
  - name: fluent-bit
    image: cr.fluentbit.io/fluent/fluent-bit:4.2.3
    args: ["-c", "/generated/fluent-bit.conf"]
    volumeMounts:
      - name: shared
        mountPath: /generated
        readOnly: true

For template expansion with envsubst, build an init image that actually includes that utility and mount the template too; a generic BusyBox image does not promise it. Check shared-file permissions for the main container's user.

Distroless reduces available tools and dependencies, but it does not make a compromised workload harmless. For temporary investigation, a Kubernetes ephemeral debug container can provide tools without rebuilding the application image. Its filesystem and privileges remain separate concerns.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting