nginxinc/docker-nginx

envsubst function not occurring for env variable

mhabsaoui opened this issue ยท 7 comments

Describe the bug

The envsubst function not occurring for env variable, when using conf template.

To reproduce

Steps to reproduce the behavior:

  1. Deploy a ReactJS app served on the NGINX Docker image using Docker Compose
  2. View output/logs/configuration on VSCode using Docker extension or in Terminal using Docker/Compose commands
  3. See nginx conf file (using interactive shell on nginx container) is the default one and is not substitued with env. file variables
  4. See error with serving URL on browser not reached on host and port defined in env. file

Expected behavior

The ReactJS app should be reachable on predefined Host/Port in browser.

Your environment

  • Version/release of Docker and method of installation : Docker engine/CLI (Docker version 26.1.1, build 4cf5afa) and Compose (Docker Compose version v2.24.0) installed using the official apt repository
  • Version/tag of the NGINX Docker image : nginx:1.26.0-alpine
  • Target deployment platform : Docker Compose running on Ubuntu 24.04 LTS

Additional context

The served ReacJS app is generated and based on the React-Admin framework.

Just trying to achieve the Out-of-the-box environment variables in Docker nginx configuration (envsubst), in deploying a ReactJS app in Docker (on Ubuntu 24.04 LTS)

I honnestly don't see what I am missing, only get the original nginx default config and no substitution occurs ๐Ÿค”

Nginx template file :

server {
    listen       ${APP_SERVER_PORT};
    server_name  ${APP_SERVER_HOST};

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Dockerfile :

FROM nginx:1.26.0-alpine as integ
# Copy nginx config template
COPY --from=builder /app/nginx.conf.template /etc/nginx/templates
WORKDIR /usr/share/nginx/html
# Remove default nginx static assets
RUN rm -rf ./*
# Copy app static assets from builder stage
COPY --from=builder /app/dist .
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
HEALTHCHECK --interval=30s --timeout=10s \
    CMD wget -nv -t1 --spider http://${APP_SERVER_HOST}:${APP_SERVER_PORT}/#/healthz || exit 1

Compose file :

version: "3.8"
services:
  react:
    platform: "linux/amd64"
    restart: always
    init: true # Run an init inside the container that forwards signals and reaps processes
    build:
      context: .
      target: integ
    env_file: ./.env
    ports:
      - ${APP_SERVER_PORT}:${APP_SERVER_PORT}
    networks:
      - frontend
networks:
  frontend:
    driver: bridge

.env file :

APP_SERVER_HOST=0.0.0.0
APP_SERVER_PORT=3001

You're redefining an ENTRYPOINT, which is supposed to launch the envsubst and other on-boot scripts.

You're redefining an ENTRYPOINT, which is supposed to launch the envsubst and other on-boot scripts.

Hi thanks for feedback ๐Ÿ‘

First, I have updated my issue to conform to new issue info...

About redefining an ENTRYPOINT, I thought (from what I have read on other similar issues) that ENTRYPOINT ["nginx", "-g", "daemon off;"] isn't redefining as long as we keep the "nginx" as first command ๐Ÿค”

So to make it work, how am I supposed to run the Nginx server, just no ENTRYPOINT instruction in Dockerfile at all ?

Thanks

Correct, you don't need to redefine ENTRYPOINT or CMD, so the defaults will be used:
https://github.com/nginxinc/docker-nginx/blob/master/stable/alpine-slim/Dockerfile#L115

Well, I have removed the ENTRYPOINT, but still the same ๐Ÿค”

docker compose -f docker-compose.integ.yml logs --follow
react-1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
react-1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
react-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
react-1  | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
react-1  | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
react-1  | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
react-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
react-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
react-1  | /docker-entrypoint.sh: Configuration complete; ready for start up
react-1  | 2024/05/06 18:29:55 [notice] 7#7: using the "epoll" event method
react-1  | 2024/05/06 18:29:55 [notice] 7#7: nginx/1.26.0
react-1  | 2024/05/06 18:29:55 [notice] 7#7: built by gcc 13.2.1 20231014 (Alpine 13.2.1_git20231014) 
react-1  | 2024/05/06 18:29:55 [notice] 7#7: OS: Linux 6.5.0-1022-oem
react-1  | 2024/05/06 18:29:55 [notice] 7#7: getrlimit(RLIMIT_NOFILE): 1048576:1048576
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker processes
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 31
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 32
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 33
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 34
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 35
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 36
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 37
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 38
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 39
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 40
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 41
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 42
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 43
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 44
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 45
react-1  | 2024/05/06 18:29:55 [notice] 7#7: start worker process 46

Screenshot from 2024-05-06 20-34-12

It seems like you don't have anything under /etc/nginx/templates/ for 20-envsubst-on-templates.sh to work on

OK I have changed the copy line in Dockerfile as follows and it seems the 20-envsubst is now triggered ๐Ÿ˜„
It's now wroking as wished ๐Ÿ‘

COPY --from=builder /app/nginx.conf.template /etc/nginx/templates/nginx.conf.template

docker compose -f docker-compose.integ.yml logs --follow
react-1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
react-1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
react-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
react-1  | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
react-1  | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
react-1  | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
react-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
react-1  | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/nginx.conf.template to /etc/nginx/conf.d/nginx.conf
react-1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
react-1  | /docker-entrypoint.sh: Configuration complete; ready for start up

Just one last curiosity question : Why the default.conf file is still there along with the generated (from envsubst?) nginx.conf one, and not replaced ?

Screenshot from 2024-05-06 22-18-17

Great to know it works!

default.conf is something we ship with the image, and it's still there to stay even with templates being used.