dockerdockerfiledocker-run

docker top: unrecognized option: /


I have a Dockerfile

FROM eclipse-temurin:17-jre-alpine
LABEL authors="sort-architectures"

WORKDIR /app/kafka

COPY ./kafka-3.5.1-src .

CMD ls -lisa bin | grep kafka-s

ENTRYPOINT ["top", "-b"]

but when I build it and run it

docker build .
docker run IMAGE-SHA256

I get the message

top: unrecognized option: /
BusyBox v1.36.1 (2023-11-07 18:53:09 UTC) multi-call binary.

Usage: top [-bmH] [-n COUNT] [-d SECONDS]

Show a view of process activity in real time.
Read the status of all processes from /proc each SECONDS
and show a screenful of them.
Keys:
        N/M/P/T: show CPU usage, sort by pid/mem/cpu/time
        S: show memory
        R: reverse sort
        H: toggle threads, 1: toggle SMP
        Q,^C: exit
Options:
        -b      Batch mode
        -n N    Exit after N iterations
        -d SEC  Delay between updates
        -m      Same as 's' key
        -H      Show threads

What's the reason? Without the line CMD ls -lisa bin | grep kafka-s it actually works. What am I doing wrong?


Solution

  • When you combine ENTRYPOINT and CMD, it's not intuitively obvious how it works.

    Docker only runs a single command when the container starts. If you have both an ENTRYPOINT and a CMD, the CMD is appended after the ENTRYPOINT into a single command.

    Your Dockerfile has both

    CMD ls -lisa bin | grep kafka-s
    ENTRYPOINT ["top", "-b"]
    

    After they're combined, the final command that Docker uses to start your container is

    top -b 'ls -lisa bin | grep kafka-s'
    

    That complains about the 'l' being an unknown option and not a '/' like you have. I don't know why that is. It might be because your Dockerfile has changed and the error message you show isn't from the version of the Dockerfile that you show.

    To run more than one command on container startup, there are different ways you can do it. Either write a script that runs the commands you need or string them together using the && or & shell operators and run them all in an single ENTRYPOINT or CMD statement.

    If you have both ENTRYPOINT and CMD, the 'normal' practice is to have the command in the ENTRYPONT and any parameters in the CMD. The CMD is easily overridden in the docker run command, so if you want different options, it's easy to do. For instance if you have

    ENTRYPOINT top
    CMD -b
    

    That will run top -b on startup.

    You can then switch out the -b option for something else on docker run. If you wanted to use -c instead, you'd do

    docker run image -c
    

    and the command run on container startup would be top -c.