Running a bash script before startup in an NGINX docker container

后端 未结 5 841
野性不改
野性不改 2021-02-15 10:56

I\'m trying to run a javascript app on localhost:8000 using docker. Part of what I would like to do is swap out some config files based on the docker run command, I\'d like to p

相关标签:
5条回答
  • 2021-02-15 11:29

    NGINX 1.19 has a folder /docker-entrypoint.d on the root where place startup scripts executed by thedocker-entrypoint.sh script. You can also read the execution on the log.

    /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration

    /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/

    /docker-entrypoint.sh: Launching

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

    /docker-entrypoint.sh: Configuration complete; ready for start up

    0 讨论(0)
  • 2021-02-15 11:34

    For my future self and everybody else, this is how you can set up variable substitution at startup (for nginx, may also work for other images):

    I've also wrote a more in depth blog post about it: 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;"]
    

    subsitute.sh: (same as @Daniel West's answer)

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

    Now you can run docker run -e TEST="set at command line" -it <image_name>

    The catch was the WORKDIR, without it the nginx command wouldn't be executed. If you want to apply this to other containers be sure to set the WORKDIR accordingly.

    If you want to do the substitution recursivly in multiple files this is the bash script you are looking for:

    # 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}"
    
    0 讨论(0)
  • 2021-02-15 11:36

    nginx container already defines ENTRYPOINT. If you define also CMD it will combine them both like 'ENTRYPOINT CMD' in such way that CMD becomes argument of ENTRYPOINT. That is why you need to redefine ENTRYPOINT to get it working.

    Usually ENTRYPOINT is defined in such way, that if you also pass CMD, it will be executed by ENTRYPOINT script. However this might not be case with every container.

    0 讨论(0)
  • 2021-02-15 11:41

    Update the CMD line as below in the your dockerfile. Please note that if runfile.sh does not succeed (exit 0; inside it) then the next nginx command will not be executed.

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

    nginx docker file is using a CMD commnd to start the server on the base image you use. When you use the CMD command in your dockerfile you overwrite the one in their image. As it is mentioned in the dockerfile documentation:

    There can only be one CMD instruction in a Dockerfile. If you list more than one CMD then only the last CMD will take effect.

    0 讨论(0)
  • 2021-02-15 11:47

    I know this is late but I found this thread while searching for a solution so thought I'd share.

    I had the same issue. Your ENTRYPOINT script should also include exec "$@"

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

    That will mean the startup CMD from the nginx:alpine container will run. The above script will inject the specified environment variables into a config file. By doing this in runtime yo can override the environment variables.

    0 讨论(0)
提交回复
热议问题