Search code examples
dockerdocker-composeaclconsul

How to run commands when a docker image runs?


I have a consul docker image which is a part of a docker-compose environment.

I have to run the command consul acl bootstrap inside the docker container, I believe mentionining it in command or entrypoint will override the default commands set for consul, how do I execute it in addition to the default commands?


Solution

  • There is no option in docker-compose to allow you to run a command after a container is started.

    What you can do is to build your own image that will execute the actions you want on startup. To do this you need to:

    1. Find out the default startup of the container (the ENTRYPOINT and CMD combined).
    2. Create a shell script that will invoke the entrypoint with the desired parameters, after which it will invoke your commands.
    3. Create a Dockerfile that is based on the original image, copy the shell script in the image and changed the entrypoint to your script
    4. Add your image and dockerfile to the docker-compose (change the current consul image to point to your image and build script)

    Here is example of a entrypoint shell script what can be used to kickstart your specific script. Place your code in the execute_after_start() function.

    entrypoint.sh

    #!/bin/bash
    set -e
    
    execute_before_start() {
        echo "Execute befor start" > /running.txt
    }
    
    execute_after_start() {
        sleep 1
        echo "Execute after start" >> /running.txt
    }
    
    execute_before_start
    echo "CALLING ENTRYPOINT WITH CMD: $@"
    exec /old_entrypoint.sh "$@" &
    daemon_pid=$!
    execute_after_start
    wait $daemon_pid
    echo "Entrypoint exited" >> running.txt
    

    The script will start the execute_before_start. When this commands are over, will start the original entry point with the arguments provided with CMD and in parallel (this is the & at the end of execute) it will start execute_after_start. When execute_after_start is over, it will wait for the original entry point to stop.

    I use sleep in the example as a simples way to assure some delay so the entry point can take the commands. Depending on the entrypoint, there might be smarter ways to assure that the entrypoint is ready to take the commands.