g medina
g medina

Reputation: 43

Is it possible to run a bash script through Dockerfile and keep the container running after docker-compose up -d?

The following install.sh script file automate the installation of my Laravel dependencies inside a container:

#!/bin/bash

LOGFILE=/tmp/install_diario_$(date +"%Y%m%d%H%M%S").log


[ -f ../.env ] || cp ../.env.docker ../.env

function error {
    echo -e "\e[31m\e[1m[ERROR]"
    echo -e 'See' $LOGFILE 'to more information\e[0m'
    exit 1
}

function ok {
    echo -e "\t\e[32m\e[1m[OK]\e[0m"
}

function installed {
    echo -e "\t\e[29m\e[1m[OK]\e[0m"
}

echo '[+] Installing PHP packages'
composer install -d "/var/www/html" 2>> $LOGFILE >> $LOGFILE

if [ $? -eq 1 ]; then
    echo '[!] Configuration Aborted. Exiting...'    
fi

echo '[+] Generating app keys'
php ../artisan key:generate #2>> $LOGFILE >> $LOGFILE
php ../artisan passport:install #2>> $LOGFILE >> $LOGFILE


echo '[+] Populating database'
# cd .. && make resetdb

echo '[+] Backend installation sucessfull.'
echo ""

php ../artisan passport:show

echo '[+] Front-end install'
npm install 2>> $LOGFILE >> $LOGFILE

However, I don't want to run this manually, but while the container is starting. So I tried using the following commands in my Dockerfile:

WORKDIR /var/www/html/docker
ADD install.sh .
RUN chmod +x ./install.sh
CMD ./install.sh

Obs.: the script is inside a folder called docker

But when I run docker-compose up --build -d my container exits after a few seconds (when the script is done).

I tried looking for solutions but none worked for me (e.g. including /bin/bash in the end of my script).

Does anyone know if this is actually possible to be done, or should I just tell my workmates to run this script manually with docker exec -it <app_id> install.sh?

Upvotes: 0

Views: 1948

Answers (2)

Yannoff
Yannoff

Reputation: 374

The problem here is the following line in your Dockerfile:

CMD ./install.sh

Indeed, your script overrides (ie is called in place of) the default php-fpm command.

Solution 1: add a line at the end of your install.sh script to invoke php-fpm

exec "php-fpm"

CAVEAT: php-fpm MUST NOT be launched as a service, it must run in the foreground to keep the container up and running.

Solution 2: implement a custom entrypoint that launches the install script

  1. Remove/comment the CMD line from the Dockerfile
  2. Implement the customized entrypoint script.

Eg:

In the Dockerfile:

# Don't override COMMAND, use the default one
#CMD ./install.sh

COPY entrypoint /usr/bin/
RUN chmod +x /usr/bin/entrypoint
ENTRYPOINT /usr/bin/entrypoint

And the entrypoint script:

# Run the install script
/path/to/install.sh

# Execute the default command, ie php-fpm
exec "$@"

*NB: Here is the minimum basic working code, feel free to customize/enrich this example - using the official docker php entrypoint for instance.

Upvotes: 1

Koala Yeung
Koala Yeung

Reputation: 7853

To a docker container, there is no distinction between its first start up from the consequence start unless you put some kind of file in a mounted volume.

What you probably want is a start up script that knows if this is the first start, run the install script, then remember to not run it again.

So besides your install script, you should probably have a start up script like this:

#!/bin/bash

# Assuming you mount this folder to your host system
MOUNTED_VAR=/var/run/laravel

# Only run the install on first run
if [ ! -f $MOUNTED_VAR/installed ]; then
  ./install.sh
fi

# Some command to start the service, for example
systemctl start php-fpm

In your docker file, you need to also include this script to start.

WORKDIR /var/www/html/docker
ADD install.sh .
RUN chmod +x ./install.sh
ADD start.sh .
RUN chmod +x ./start.sh
CMD ./start.sh

Upvotes: 0

Related Questions