在NGINX docker容器中启动前运行bash脚本

Running a bash script before startup in an NGINX docker container

本文关键字:运行 bash 脚本 启动 NGINX docker      更新时间:2023-09-26

我正在尝试使用docker在localhost:8000上运行javascript应用程序。我想做的一部分是根据docker运行命令交换出一些配置文件,我想将一个环境变量传递到容器中,以便bash脚本可以将其用作参数。

我的dockerfile是这样的:

FROM nginx
COPY . /usr/share/nginx/html
CMD ["bash","/usr/share/nginx/html/runfile.sh"]

bash脚本是这样的:

#!/bin/bash
if [ "$SECURITY_VERSION" = "OPENAM" ]; then
    sed -i -e 's/localhost/openam/g' authConfig.js
fi
docker run -p 8000:80 missioncontrol:latest -e SECURITY_VERSION="TEST"

Docker给了我一个异常,说-e exec command not found.

然而,如果我改变dockerfile使用ENTRYPOINT而不是CMD, -e标志工作,但web服务器不启动。

我在这里错过了什么吗?ENTRYPOINT是否被重写了?

编辑:

所以我已经更新了我的dockerfile使用ENTRYPOINT ["bash","/usr/share/nginx/html/runfile.sh", ";", " nginx -g daemon off;"]

但是docker容器仍然关闭。我是不是漏掉了什么?

NGINX 1.19在根目录下有一个/docker-entrypoint.d文件夹,用来存放docker-entrypoint.sh脚本执行的启动脚本。您还可以在日志中读取执行情况。

/docker-entrypoint.sh:/docker-entrypoint。D/不是空的,是会的尝试执行配置

/docker-entrypoint.sh/docker-entrypoint.d/

/docker-entrypoint.sh:推出

[..........]

/docker-entrypoint.sh:配置完成;准备启动

对于我自己和其他人,这是如何在启动时设置变量替换(对于nginx,也可能适用于其他图像):

我还写了一篇更深入的博客文章:https://danielhabenicht.github.io/docker/angular/2019/02/06/angular-nginx-runtime-variables.html

Dockerfile:

FROM nginx
ENV TEST="Hello variable"
WORKDIR /etc/nginx
COPY ./substituteEnv.sh ./substituteEnv.sh
# Execute the subsitution script and pass the path of the file to replace
ENTRYPOINT ["./substituteEnv.sh", "/usr/share/nginx/html/index.html"]
CMD ["nginx", "-g", "daemon off;"]

replace .sh:(与@Daniel West的回答相同)

#!/bin/bash
if [[ -z $1 ]]; then
    echo 'ERROR: No target file given.'
    exit 1
fi
#Substitute all environment variables defined in the file given as argument
envsubst ''$TEST '$UPSTREAM_CONTAINER '$UPSTREAM_PORT' < $1 > $1
# Execute all other paramters
exec "${@:2}"

现在可以运行docker run -e TEST="set at command line" -it <image_name>

catch是WORKDIR,没有它nginx命令将无法执行。如果您想将此应用于其他容器,请确保相应地设置WORKDIR

如果你想在多个文件中递归地进行替换,这就是你要找的bash脚本:

# Substitutes all given environment variables
variables=( TEST )
if [[ -z $1 ]]; then
    echo 'ERROR: No target file or directory given.'
    exit 1
  fi
for i in "${variables[@]}"
do
  if [[ -z ${!i} ]]; then
    echo 'ERROR: Variable "'$i'" not defined.'
    exit 1
  fi
  echo $i ${!i} $1
  # Variables to be replaced should have the format: ${TEST}
  grep -rl $i $1 | xargs sed -i "s/'${$i}/${!i}/Ig"
done
exec "${@:2}"

NginX图像包含docker-entrypoint.d,并且在容器启动时将查找位于那里的任何脚本。您可以在docker构建期间添加自定义脚本。我还发现,如果您使用的是alpine image,则没有安装bash,因此您可以通过运行:

自己添加它:
RUN apk update
RUN apk upgrade
RUN apk add bash
样本DockerFile:

FROM nginx:alpine
EXPOSE 443
EXPOSE 80
RUN apk update
RUN apk upgrade
RUN apk add bash
COPY ["my-script.sh", "/docker-entrypoint.d/my-script.sh"]
RUN chown nginx:nginx /docker-entrypoint.d/my-script.sh
USER nginx

为了限制自定义脚本的执行范围,强烈建议以非特权用户身份运行容器。

我知道这是晚了,但我发现这个线程,而寻找一个解决方案,所以我想我分享。

我也有同样的问题。您的ENTRYPOINT脚本还应该包含exec "$@"

#!/bin/sh
set -e
envsubst ''$CORS_HOST '$UPSTREAM_CONTAINER '$UPSTREAM_PORT' < /srv/api/default.conf > /etc/nginx/conf.d/default.conf
exec "$@"

这将意味着启动CMD从nginx:alpine容器将运行。上述脚本将把指定的环境变量注入到配置文件中。通过在运行时这样做,您可以覆盖环境变量。

在dockerfile中按如下方式更新CMD行。请注意,如果runfile.sh没有成功(exit 0;在其中),那么下一个nginx命令将不会执行。

FROM nginx
COPY . /usr/share/nginx/html
CMD /usr/share/nginx/html/runfile.sh && nginx -g 'daemon off;'

nginx docker文件使用CMD命令在您使用的基本映像上启动服务器。当您在dockerfile中使用CMD命令时,您会覆盖其映像中的CMD命令。正如dockerfile文档中提到的:

一个Dockerfile中只能有一个CMD指令。如果您列出多个CMD,则只有最后一个CMD生效。

nginx容器已经定义了ENTRYPOINT。如果你也定义了CMD,它会像"ENTRYPOINT CMD"一样将它们组合在一起,这样CMD就变成了ENTRYPOINT的参数。这就是为什么你需要重新定义ENTRYPOINT来让它工作。

通常ENTRYPOINT是这样定义的,如果你也传递CMD,它将由ENTRYPOINT脚本执行。然而,这可能不是每个容器的情况。