Search code examples
dockerenvironment-variablesdocker-swarmdocker-entrypoint

Exported environmental variable via docker entrypoint are not shown when logging into the container


Assume a simple Dockerfile

FROM php-fpm:8
ADD entrypoint.sh .
RUN chmod +x entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
CMD ["php-fpm"]

In the entry-point script I just export a variable and print the environment

#!/bin/bash

set -e

export FOO=bar
env // just print the environment while entry point is running

exec "$@"

Then I build the image as myimage and use it to deploy a stack in docker swarm mode

docker stack deploy -c docker-compose.yml teststack


// The docker-compose.yml file used is the following:

app:
  image: myimage:latest
  environment:
    APP_ENV: production

Now the question: If a check the logs of the app service I can see (because of the env command in the entry point) that the FOO variable is exported

docker service logs teststack_app 

teststack_app.1.nbcqgnspn1te@soulatso    | PWD=/var/www/html
teststack_app.1.nbcqgnspn1te@soulatso    | FOO=bar
teststack_app.1.nbcqgnspn1te@soulatso    | HOME=/root

However if I login in the running container and manually run env the FOO variable is not shown

docker container exec -it teststack_app.1.nbcqgnspn1tebirfatqiogmwp bash

root@df9c6d9c5f98:/var/www/html# env // run env inside the container

PWD=/var/www/html
HOME=/root
// No FOO variable :(

What I am missing here?


Solution

  • A debugging shell you launch via docker exec isn't a child process of the main container process, and doesn't run the entrypoint itself, so it doesn't see the environment variables that are set there.

    Depending on what you're trying to do, there are a couple of options to get around this.

    If you're just trying to inspect what your image build produced, you can launch a debugging container instead. The command you pass here will override the CMD in the Dockerfile, and when your entrypoint script does something like exec "$@" to run the command it gets passed, it will run this command instead. This lets you inspect things in an environment just after your entrypoint's first-time setup has happened.

    docker-compose run app env | grep FOO
    docker-compose run app bash
    

    Or, if the only thing your entrypoint script is to set environment variables, you can explicitly invoke it.

    docker-compose exec app ./entrypoint.sh bash
    

    It is important that your entrypoint script accept an ordinary command as parameters. If it is a shell script, it should use something like exec "$@" to launch the main container process. If your entrypoint ignores its parameters and launches a fixed command, or if you've set ENTRYPOINT to a language interpreter and CMD to a script name, these debugging techniques will not work.