How to run commands when a docker image runs?

Viewed 771

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?

2 Answers

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.

As others have commented, its not possible in compose to run additional commands after a container has started.

Alternatively you can explicitly specify the master token's secret ID by specifying acl.tokens.master in the Consul server's configuration. The easiest way to do this with the Docker image is to pass the configuration using the CONSUL_LOCAL_CONFIG environment variable (see Docker-Consul: Using the container).

For example:

---
version: "3.8"
services:
  consul:
    image: consul
    ports:
      - "8500:8500/tcp"
    environment:
      CONSUL_LOCAL_CONFIG: >
        {"acl": {"enabled": true, "tokens": {"master": "A8D89992-A3DB-46E3-A528-8F97CFEDB183"} }}

This has the obvious downside of hard coding a token into your Compose configuration, but also avoids the complexities of trying to run consul acl bootstrap using a custom entrypoint.

You only need to provide this environment variable when the cluster is first initialized. After that, Consul persists this token data in a Docker volume mounted at /consul/data. Any modifications to the tokens (including the master token) need to be performed using consul acl token or the /v1/acl/token API endpoints.

Related