简体   繁体   中英

Unable to run custom script on container startup

I am trying to setup Clair (Docker image vulnerability scanner tool). https://github.com/coreos/clair

I have Clair working ok locally using docker-compose. The problem is that when I deploy it to AWS I need to specify the postgres server address, username and password etc. The postgres server address is not known when the image is built, so it cannot be included when the Clair docker image is built. It needs to be customised at container/image startup.

For other apps that use a database I usually just customise the docker image and add a script (that runs at startup) that uses SED to to insert in the correct values (taken from environment variables) to the apps config file.

For example:

Dockerfile

FROM quay.io/coreos/clair:latest

COPY /docker/clair/runtime.sh /runtime.sh
RUN chmod +x /runtime.sh

CMD ["/runtime.sh"]

runtime.sh

sed -i -e "s,#POSTGRES_SERVER#,$POSTGRES_SERVER,g" config.yaml

For some reason the above approach will not work with the Clair docker image. This approach has worked for many other mainstream images so I am thinking it is something special about the Clair image.

I don't get any errors, it just ignores the CMD ["/runtime.sh"] in my dockerfile and starts like it would normally.

Is anyone able to point out how I can get my custom script running or point out another way to achieve the same thing?

=========== UPDATE WITH SOLUTION ===========

The problem was that the Clair image is based on BusyBox which by default uses the ash shell and the shell script I wrote/am using is written for the bash shell. Perhaps this should have been obvious but I am somewhat new to writing linux shell scripts and had not yet come across this.

I realised this after testing mchawre's answer which avoids the problem I experienced as it does not use a shell script.

So the solution I used was to install bash into the image and then I am able to use my usual bash shell script on container startup.

Dockerfile

FROM quay.io/coreos/clair:latest

RUN apk --no-cache upgrade
RUN apk add --no-cache curl py-pip bash postgresql-client figlet \
 && curl -L https://github.com/optiopay/klar/releases/download/v2.4.0/klar-2.4.0-linux-amd64 \
  > /usr/local/bin/klar \
 && chmod +x /usr/local/bin/klar \
 && pip install awscli

# Copy in custom Clair config file
COPY /docker/clair/config.yaml /etc/clair/config.yaml

# Env Vars for use with Klar CLI
ENV CLAIR_ADDR http://127.0.0.1:6060

# Copy runtime script & make it executable
COPY /docker/clair/runtime.sh /runtime.sh
RUN chmod +x /runtime.sh

# Override the parent images ENTRYPOINT
# Run a script on container startup which does a few things in addition to starting Clair at the end.
# Note, this script is a BASH script. It is critical that you install bash into the docker image or this script will
# fail with errors that are not very helpful.
ENTRYPOINT ["/runtime.sh"]

runtime.sh (small extract)

#!/bin/bash

echo "======= Configuring config.yaml ====="
sed -i -e "s,#POSTGRES_USER#,$POSTGRES_USER,g" /etc/clair/config.yaml
sed -i -e "s,#POSTGRES_PASSWORD#,$POSTGRES_PASSWORD,g" /etc/clair/config.yaml
sed -i -e "s,#POSTGRES_URL#,$POSTGRES_URL,g" /etc/clair/config.yaml

/clair -config=/etc/clair/config.yaml

Please check this .

Putting that sed command inside dockerfile CMD should work.

CMD sed -i "s/localhost/$DB_HOST/" /config/config.yaml && exec /clair -config=/config/config.yaml

The approach the Clair documentation seems to endorse is to take the sample config file from the source tree, customize it to taste, and inject it into the container with a docker run -v option. So more or less

docker network create clairnet
docker run -d \
  --net clairnet \
  --name clairpg \
  postgres:9.6
mkdir clair_config
sed 's/host=localhost/host=clairpg/' config.yaml.sample > clair_config/config.yaml
docker run -d \
  --net clairnet \
  -v $PWD/clair_config:/config \
  -p 6060:6060 \
  -p 6061:6061 \
  quay.io/coreos/clair:latest \
  -config=/config/config.yaml

(This is a generically useful approach, and might be easier than trying to patch config files at container startup time.)

On the off chance you're running this in Kubernetes, the source tree also includes a Helm chart, and that uses Go templates to populate the configuration in a ConfigMap at install time. This is a very Kubernetes-specific solution, though, and I wouldn't suggest running Kubernetes just to be able to run things this way.

Otherwise you're stuck looking at the image's Dockerfile (in the root of the repository). That includes this line:

ENTRYPOINT ["/usr/bin/dumb-init", "--", "/clair"]

If you build a derived image with its own CMD , that gets passed as additional arguments to the ENTRYPOINT , which in this case means it gets passed as arguments to Clair; a caller can't provide an alternate command, launch a debugging shell, or in your case inject an extra startup-time step without completely overriding the entrypoint value.

You can get around this by writing your own entrypoint script. I'd suggest splitting out the command to run ( /clair ) from the setup steps. The script could look like

#!/bin/sh
# I am /docker-entrypoint.sh, with mode 0755
sed "s/host=localhost/host=$PGHOST/" /config/config.yaml.sample > /config/config.sample
exec /usr/bin/dumb-init -- "$@"

and then your derived Dockerfile something like

FROM quay.io/coreos/clair
COPY docker-entrypoint.sh /
RUN chmod 0755 /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["/clair"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM