How can I run script automatically after Docker container startup

12/6/2017

I'm using Search Guard plugin to secure an elasticsearch cluster composed of multiple nodes. Here is my Dockerfile:

#!/bin/sh
FROM docker.elastic.co/elasticsearch/elasticsearch:5.6.3

USER root

# Install search guard
RUN bin/elasticsearch-plugin install --batch com.floragunn:search-guard-5:5.6.3-16 \
    && chmod +x \
        plugins/search-guard-5/tools/hash.sh \
        plugins/search-guard-5/tools/sgadmin.sh \
        bin/init_sg.sh \
    && chown -R elasticsearch:elasticsearch /usr/share/elasticsearch

USER elasticsearch

To initialize SearchGuard (create internal users and assign roles). I need to run the script init_sg.sh after the container startup. Here is the problem: Unless elasticsearch is running, the script will not initialize any security index.

The script's content is :

sleep 10
plugins/search-guard-5/tools/sgadmin.sh -cd config/ -ts config/truststore.jks -ks config/kirk-keystore.jks -nhnv -icl

Now, I just run the script manually after the container startup but since I'm running it on Kubernetes.. Pods may get killed or fail and get recreated automatically for some reason. In this case, the plugin have to be initialized automatically after the container startup!

So how to accomplish this? Any help or hint would be really appreciated.

-- PhiloJunkie
docker
dockerfile
elasticsearch
elasticsearch-plugin
kubernetes

4 Answers

12/6/2017

Not sure this will solves your problem, but its worth check my repo'sDockerfile

I have created a simple run.sh file copied to docker image and in the Dockerfile I wrote CMD ["run.sh"]. In the same way define whatever you want in run.sh and write CMD ["run.sh"]. You can find another example like below

Dockerfile

FROM java:8

RUN apt-get update && apt-get install stress-ng -y 
ADD target/restapp.jar /restapp.jar 
COPY dockerrun.sh /usr/local/bin/dockerrun.sh 
RUN chmod +x /usr/local/bin/dockerrun.sh 
CMD ["dockerrun.sh"]

dockerrun.sh

#!/bin/sh
java -Dserver.port=8095 -jar /restapp.jar &
hostname="hostname: `hostname`"
nohup stress-ng --vm 4 &
while true; do
  sleep 1000
done
-- Veerendra Kakumanu
Source: StackOverflow

12/6/2017

The image itself has an entrypoint ENTRYPOINT ["/run/entrypoint.sh"] specified in the Dockerfile. You can replace it by your own script. So for example create a new script, mount it and first call /run/entrypoint.sh and then wait for start of elasticsearch before running your init_sg.sh.

-- Jonathan Lechner
Source: StackOverflow

4/17/2019

I was trying to solve the exact problem. Here's the approach that worked for me.

  1. Create a separate shell script that checks for ES status, and only start initialization of SG when ES is ready:

Shell Script

#!/bin/sh

echo ">>>>  Right before SG initialization <<<<"
# use while loop to check if elasticsearch is running 
while true
do
    netstat -uplnt | grep :9300 | grep LISTEN > /dev/null
    verifier=$?
    if [ 0 = $verifier ]
        then
            echo "Running search guard plugin initialization"
            /elasticsearch/plugins/search-guard-6/tools/sgadmin.sh -h 0.0.0.0 -cd plugins/search-guard-6/sgconfig -icl -key config/client.key -cert config/client.pem -cacert config/root-ca.pem -nhnv
            break
        else
            echo "ES is not running yet"
            sleep 5
    fi
done

Install script in Dockerfile

You will need to install the script in container so it's accessible after it starts.

COPY sginit.sh /
RUN chmod +x /sginit.sh

Update entrypoint script

You will need to edit the entrypoint script or run script of your ES image. So that it starts the sginit.sh in the background BEFORE starting ES process.

# Run sginit in background waiting for ES to start
/sginit.sh &

This way the sginit.sh will start in the background, and will only initialize SG after ES is started.

The reason to have this sginit.sh script starts before ES in the background is so that it's not blocking ES from starting. The same logic applies if you put it after starting of ES, it will never run unless you put the starting of ES in the background.

-- nafooesi
Source: StackOverflow

12/6/2017

I would suggest to put the CMD in you docker file to execute the script when the container start

FROM debian
RUN apt-get update && apt-get install -y nano && apt-get clean
EXPOSE 8484
CMD ["/bin/bash", "/opt/your_app/init.sh"]

There is other way , but before using this look at your requirement,

    ENTRYPOINT "put your code here" && /bin/bash
    #exemple ENTRYPOINT service nginx start && service ssh start &&/bin/bash "use && to separate your code"
-- Sohan
Source: StackOverflow