无法在容器启动时 运行 自定义脚本
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"]
我正在尝试设置 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"]