skip to Main Content

I have created the following docker-compose.yml:

version: "3.8"

services:
  app:
    image: my-image
    build:
      context: .
      dockerfile: Dockerfile
    working_dir: /src
    command: python ${SCRIPT}
    environment:
      - .env

  app-dev:
    extends:
      service: app
    volumes:
      - ./src:/src

My .env file has one line:

SCRIPT=./tutorial_00/docker_test.py

I will now do the following steps:

  1. Build the docker image: docker-compose up --build app
    This will build the image and run the docker_test.py script
  2. Now I want to run a different python script using this command: docker-compose run --rm -e SCRIPT=tutorial_01/main.py app
    This should override the default value for the SCRIPT variable which was retrieved from the .env file with tutorial_01/main.py. However it ignores this flag and still runs the default script. I don’t really know why. It seems like the parameter is completely ignored.

If I run the following command docker-compose run --rm -e SCRIPT=./tutorial_01/main.py app env it shows me that the variable was set successfully:

PATH=/venv/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=e420aa256ae69
TERM=xterm
SCRIPT=./tutorial_01/main.py
LANG=C.UTF-8
GPG_KEY=A035C8C19219BA821E8D684696D
PYTHON_VERSION=3.11.9
PYTHON_PIP_VERSION=24.0
PYTHON_SETUPTOOLS_VERSION=65.5.1

If I set ./tutorial_01/main.py as the default value in .env it successfully runs this file instead. So the path is definetly valid.

2

Answers


  1. Chosen as BEST ANSWER

    EDIT: A real answer was given and marked as such. I'm just leaving this here fyi. However I'd not recommend doing it this way. Use the solution provided by "Hans Kilian" instead.

    I experimented a little bit and I'm starting to think that variables inside the command: block are not possible. I assume the command you are actually running has to be static. Therefore I am using the following workaround. I run a static file which will run the correct file for me based on the given environment variable. I updated the docker-compose.yml as follows:

    version: "3.8"
    
    services:
      app:
        image: my-image
        build:
          context: .
          dockerfile: Dockerfile
        working_dir: /src
        command: python start.py
        environment:
          - SCRIPT=./tutorial_00/docker_test.py
    
      app-dev:
        extends:
          service: app
        volumes:
          - ./src:/src
    

    Then I created a new python file called start.py inside my docker src directory which will get the ENV SCRIPT and runs a python file at that location:

    import os
    import subprocess
    import sys
    
    
    def main():
        # Retrieve the environment variable 'SCRIPT'
        script_path = os.getenv('SCRIPT')
    
        if not script_path:
            print("Error: The 'SCRIPT' environment variable is not set.")
            sys.exit(1)
    
        # Check if the file exists
        if not os.path.isfile(script_path):
            print(f"Error: The file at '{script_path}' does not exist.")
            sys.exit(1)
    
        # Execute the Python script
        try:
            subprocess.run([sys.executable, script_path], check=True)
        except subprocess.CalledProcessError as e:
            print(
                f"Error: The script at '{script_path}' failed with exit code {e.returncode}.")
            sys.exit(e.returncode)
    
    
    if __name__ == "__main__":
        main()
    

    Now I can successfully run any python script by passing the SCRIPT variable during the docker-compose run command:

    docker-compose run --rm -e SCRIPT=tutorial_02/main.py app
    

    This definitely works but it feels like a bit of a "shady" workaround. Let me know if there is a better way to do this.


  2. When talking about compose and environment variables, you have to be careful about if the variables are for compose or for the container.

    The -e option with docker compose run is for the container. So when you run

    docker-compose run --rm -e SCRIPT=./tutorial_01/main.py app env
    

    the SCRIPT variable is set inside the container and is not available in the compose file.

    To make a variable available to compose, you can set it on the host. If you do do

    SCRIPT=./tutorial_01/main.py docker-compose run --rm app env
    

    the script variable is set on the host, docker compose has access to it and your compose file will work as expected.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search