Search code examples
dockerdockerfilegitlab-ci

Login shell does not source .profile in Gitlab CI


I have this Dockerfile:

FROM ubuntu:24.04

COPY setup.sh /opt/

RUN echo 'echo Hello from .profile' >> /root/.profile
RUN echo 'source /opt/setup.sh' >> /root/.profile

CMD ["/bin/bash", "-l"]

The contents of the setup.sh is:

#!/bin/bash

echo "Executing setup script"

say_hello() {
    echo "Hello World!"
}

I would like to use the Docker image tagged with test to run the following Gitlab CI testcase:

foo:
  image: registry.git.my-domain.com/test
  script:
    - ls /opt
    - say_hello

This test fails. I get the following output:

Using docker image sha256:fff9c67f9 ...
$ ls /opt
setup.sh
$ say_hello
/usr/bin/bash: line 148: say_hello: command not found
  1. It seems that .profile was not sourced, as the say_hello command should be available if it were. Why does this happen? In my Dockerfile, I am setting up a login shell that should execute .profile.

  2. Do I really have to manually source setup.sh in the testcase foo? I would like to avoid this but to provide a Docker container that does it automatically.


Solution

  • Why does this happen?

    That's simple - it is not running a login shell.

    In my Dockerfile, I am setting up a login shell that should execute .profile.

    You are setting CMD. Gitlab executes it's own CMD.

    Do I really have to manually source setup.sh in the testcase foo?

    No, but that is the best solution, is explicit and readable. Usually put in before_script:.

    I would like to avoid this but to provide a Docker container that does it automatically.

    You can use ENTRYPOINT to set the entrypoint.

    You can use BASH_ENV environment variable to inject anything to any bash session. You can set it with ENV.

    don't think an entrypoint script would work because variables, aliases etc. defined there won't be visible after the script terminates.

    Do not terminate entrypoint. You can export a function in Bash with export -f.