'How to execute a shell command before the ENTRYPOINT via the dockerfile

I have the following file for my nodejs project

FROM node:boron

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install



# Bundle app source
COPY . /usr/src/app

# Replace with env variable
RUN envsubs < fil1 > file2

EXPOSE 8080
CMD [ "npm", "start" ]

I run the docker container with the -e flag providing the environment variable

But I do not see the replacement. Will the Run ccommand be excuted when the env variable is available?



Solution 1:[1]

Will the Run ccommand be excuted when the env variable is available?

Environnement variables set with -e flag are set when you run the container.

Problem is, Dockerfile is read on container build, so the RUN command will not be aware of thoses environnement variables.

The way to have environment variables set on build, is to add in your Dockerfile, ENV line. (https://docs.docker.com/engine/reference/builder/#/environment-replacement)

So your Dockerfile may be :

FROM node:latest

WORKDIR /src
ADD package.json .

ENV A YOLO

RUN echo "$A"

And the output :

$ docker build .
Sending build context to Docker daemon  2.56 kB
Step 1 : FROM node:latest
 ---> f5eca816b45d
Step 2 : WORKDIR /src
 ---> Using cache
 ---> 4ede3b23756d
Step 3 : ADD package.json .
 ---> Using cache
 ---> a4671a30bfe4
Step 4 : ENV A YOLO
 ---> Running in 7c325474af3c
 ---> eeefe2c8bc47
Removing intermediate container 7c325474af3c
Step 5 : RUN echo "$A"
 ---> Running in 35e0d85d8ce2
YOLO
 ---> 78d5df7d2322

You see at the before-last line when the RUN command launched, the container is aware the envrionment variable is set.

Solution 2:[2]

For images with bash as the default entrypoint, this is what I do to allow myself to run some scripts before shell start if needed:

FROM ubuntu
COPY init.sh /root/init.sh
RUN echo 'a=(${BEFORE_SHELL//:/ }); for c in ${a[@]}; do source $x; done' >> ~/.bashrc

and if you want to source a script at container login you pass its path in the environment variable BEFORE_SHELL. Example using docker-compose:

version: '3'
services:
  shell:
    build:
      context: .
    environment:
      BEFORE_SHELL: '/root/init.sh'

Some remarks:

  • If BEFORE_SHELL is not set then nothing happens (we have the default behavior)
  • You can pass any script path available in the container, included mounted ones
  • The scripts are sourced so variables defined in the scripts will be available in the container
  • Multiple scripts can be passed (use a : to separate the paths)

Solution 3:[3]

I had an extremely stubborn container that would not run anything on startup. This technique workd well, and took me a day to find as every single other possible technique failed.

  • Run docker inspect postgres to find entrypoint script. In this case, it was docker-entrypoint.sh. This might vary by container type and Docker version.
  • Open a shell into the container, then find the full path: find / -name docker-entrypoint.sh
  • Inspect the file: cat /usr/local/bin/docker-entrypoint.sh

In the Dockerfile, use SED to insert line 2 (using 2i).

# Insert into Dockerfile 
RUN sed -i '2iecho Run on startup as user `whoami`.' /usr/local/bin/docker-entrypoint.sh

In my particular case, Docker ran this script twice on startup: first as root, then as user postgres. Can use the test to only run the command under root.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 piarston
Solution 3