How the shell with Docker executor is selected

I’m using shared runners on Gitlab.com page with a custom Docker image. It is based on Alpine which contains sh but also bash is installed in a later step.

How do I know, which shell the Docker executor is using for executing scripts from .gitlab-ci.yml file? Is that sh or bash?

This documentation (The Docker executor | GitLab) says that sh, bash and pwsh is supported. However if Docker image contains more of them, which has higher priority?

I would love to know this as well. I have a container which uses
ENTRYPOINT ["/bin/bash", "-l", "-c"]
and has bash installed, but still I cannot make it run using bash instead of sh.

I also set the shell option of the [[runners]] section to bash, to no avail.

I wasn’t able to find it in the documentation, but I have found that in the source code of Runner.
I wrote a post about it here: Shell conditions in Gitlab CI - DEV Community 👩‍💻👨‍💻

And here is the script which is responsible for selecting the shell.

Thank you for that.

Using one of my images, which has ENTRYPOINT ["/bin/bash", "-l", "-c"] and a working bash, I am still getting that GitLab executes scripts using sh:

image:
    name:my_image
    entrypoint: [ "/bin/bash", "-lc" ] # Just for good measure, force it

stages:
    - test

job:
    stage: test
    script:
        - '[ -x /bin/bash ] && echo BASH IS OK' # OK
        - '[ -x /bin/sh ]   && echo   SH IS OK' # OK
        - bash -c 'echo $0' # BASH
        - echo $0 # SH: why?

I am sincerely lost.
This does not happen with the image my image is based on: debian:bookworm-slim, to which I actually only add a couple of things and set the environment.

I even manually ran:

docker run --rm -it --entrypoint "sh" my_image -c 'if [ -x /usr/local/bin/bash ]; then
  echo exec /usr/local/bin/bash -l
  elif [ -x /usr/bin/bash ]; then
  echo exec /usr/bin/bash -l
  elif [ -x /bin/bash ]; then
  echo exec /bin/bash -l
  elif [ -x /usr/local/bin/sh ]; then
  echo exec /usr/local/bin/sh -l
  elif [ -x /usr/bin/sh ]; then
  echo exec /usr/bin/sh -l
  elif [ -x /bin/sh ]; then
  echo exec /bin/sh -l
  elif [ -x /busybox/sh ]; then
  echo exec /busybox/sh -l
  else
  echo shell not found
  exit 1
  fi'

and got exec /bin/bash -l in response!