Search code examples
bashdocker

How can I run bash in a docker container?


I am able to run arbitrary shell commands in a container created from docker/whalesay image.

$ docker run docker/whalesay ls -l
total 56
-rw-r--r-- 1 root root  931 May 25  2015 ChangeLog
...

However, I am unable to run bash in a container created from this image:

$ docker run docker/whalesay bash

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                         PORTS               NAMES
7ce600cc9904        docker/whalesay     "bash"                   5 seconds ago       Exited (0) 3 seconds ago                           loving_mayer

Why did it not work? How can I make it work?


Solution

  • If you docker run without attaching a tty, and only call bash, then bash finds nothing to do, and it exits. That's because by default, a container is non-interactive, and a shell that runs in non-interactive mode expects a script to run. Absent that, it will exit.

    To run a disposable new container, you can simply attach a tty and standard input:

    docker run --rm -it --entrypoint bash <image-name-or-id>
    

    Or to prevent the above container from being disposed, run it without --rm.

    Or to enter a running container, use exec instead:

    docker exec -it <container-name-or-id> bash
    

    In comments you asked

    Do you know what is the difference between this and docker run -it --entrypoint bash docker/whalesay?

    In the two commands above, you are specifying bash as the CMD. In this command, you are specifying bash as the ENTRYPOINT.

    Every container is run using a combination of ENTRYPOINT and CMD. If you (or the image) does not specify ENTRYPOINT, the default entrypoint is /bin/sh -c.

    So in the earlier two commands, if you run bash as the CMD, and the default ENTRYPOINT is used, then the container will be run using

    /bin/sh -c bash
    

    If you specify --entrypoint bash, then instead it runs

    bash <command>
    

    Where <command> is the CMD specified in the image (if any is specified).

    EDIT May 2024

    Responding to a recent question, updating with a bit more detail. How do you know what the ENTRYPOINT and CMD are?

    You can inspect an image (and use something like jless or jq to easily find things in the JSON output, if desired). For example:

    ❯ docker inspect docker/whalesay | jq '.[].Config.Entrypoint,.[].Config.Cmd'
    null
    [
      "/bin/bash"
    ]
    

    Here we see the ENTRYPOINT is null and the CMD is ["/bin/bash"]. In this case, Docker will execute the CMD with a system call.

    The exact behaviors are in the Docker documentation. As of today this link will take you there, but the link might change in the future.