无法在容器启动时 运行 自定义脚本

Unable to run custom script on container startup

我正在尝试设置 Clair(Docker 图像漏洞扫描工具)。 https://github.com/coreos/clair

我让 Clair 在本地使用 docker-compose 正常工作。问题是,当我将它部署到 AWS 时,我需要指定 postgres 服务器地址、用户名和密码等。在构建映像时,postgres 服务器地址是未知的,因此在 Clair docker 时无法包含它图像已构建。需要在 container/image 启动时自定义。

对于其他使用数据库的应用程序,我通常只是自定义 docker 图像并添加一个脚本(在启动时运行),该脚本使用 SED 插入正确的值(从环境变量中获取)到应用程序配置文件。

例如:

Docker文件

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

由于某些原因,上述方法不适用于克莱尔 docker 图像。这种方法适用于许多其他主流图像,所以我认为这对 Clair 图像来说很特别。

我没有收到任何错误,它只是忽略了我的 docker 文件中的 CMD ["/runtime.sh"] 并正常启动。

有谁能指出我如何获得我的自定义脚本 运行 或指出另一种方法来实现同样的事情?

=========== 更新解决方案 ===========

问题是 Clair 图像基于 BusyBox,它默认使用 ash shell 而我 wrote/am 使用的 shell 脚本是为bash shell。也许这应该是显而易见的,但我对编写 linux shell 脚本有些陌生,还没有遇到过这个。

我在测试了 mchawre 的回答后意识到了这一点,这避免了我遇到的问题,因为它不使用 shell 脚本。

所以我使用的解决方案是将 bash 安装到映像中,然后我就可以在容器启动时使用我常用的 bash shell 脚本。

Docker文件

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(小摘录)

#!/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

请检查this

sed 命令放入 dockerfile CMD 应该可以。

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

来自源代码树的方法 the Clair documentation seems to endorse is to take the sample config file,根据需要自定义它,并使用 docker run -v 选项将其注入容器。所以或多或少

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

(这是一种普遍有用的方法,可能比尝试在容器启动时修补配置文件更容易。)

如果您 运行 在 Kubernetes 中使用它,源代码树还包含一个 Helm 图表,并且在安装时使用 Go templates to populate the configuration in a ConfigMap。不过,这是一个非常 Kubernetes-specific 的解决方案,我不建议 运行 宁 Kubernetes 只是为了能够 运行 这样的事情。

否则你将无法查看 the image's Dockerfile(在存储库的根目录中)。这包括这一行:

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

如果您使用自己的 CMD 构建派生图像,它会作为附加参数传递给 ENTRYPOINT,在这种情况下,这意味着它会作为参数传递给 Clair;调用者不能提供备用命令,启动调试 shell,或者在您的情况下注入额外的 startup-time 步骤而不完全覆盖入口点值。

您可以通过编写自己的入口点脚本来解决这个问题。我建议从设置步骤中将命令拆分为 运行 (/clair)。该脚本可能看起来像

#!/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 -- "$@"

然后你派生的 Dockerfile 类似于

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