Closed mjswensen closed 4 years ago
Same problem here. I also tried manually running nginx -g 'daemon off;' -T
and it's using the original default.conf
only.
Using nginx:1.19.0-alpine
I've just tried it and it works.
Can you "docker pull nginx" or "nginx:1.19.0-alpine" and then docker-compouse up -d
and then show the output of docker logs
for the launched container?
For my case, I know what the problem was.
I was overriding CMD
in my Dockefile
. By taking a look at the content of the entrypoint script of the Nginx docker image:
if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
This means that, if your custom CMD
does not start with nginx
or nginx-debug
(which was the case for me), none of the /docker-entrypoint.d
scripts will be run because of how docker-entrypoint.sh
works. The Nginx template compilation step is one of those scripts.
This is very unclear in the README
of the image on dockerhub and I was only able to figure it out by looking at the code of the entrypoint script.
My solution was to simply add whatever I want to execute on entrypoint to a custom script and copy it to /docker-entrypoint.d/
so that it gets executed with the existing scripts, and just not overriding CMD
or ENTRYPOINT
in my custom image Dockerfile
.
I think the README
should be updated to reflect how this custom templating function actually works and how the entrypoint works too.
I also recommend taking a look at this how CMD
and ENTRYPOINT
interact.
I also recommend taking a look at this how
CMD
andENTRYPOINT
interact.
Is there something there that should be considered?
Unfortunately that table isn't correct/complete. Everything under the ENTRYPOINT exec_entry p1_entry
should start with /bin/sh -c 'exec_entry p1_entry'
(the quotes are important since it is a single argument for the -c
of /bin/sh
) and CMD
needs to be shown as extra arguments to the sh -c
. While these extra args wouldn't usually have an effect, they do become arguments to the "script":
Regardless, the entrypoint and command here are working as designed (and very similar to most other images in the official-images program, e.g. redis).
@TamerShlash :
I was overriding
CMD
in myDockefile
.
Same for me (but ENTRYPOINT). Removing ENTRYPOINT from child image resolved the issue..
I just tried and it works for me.
My docker-compose file :
version: '3.7'
services:
nginx:
container_name: nginx
environment:
NGINX_PORT: 80
image: nginx
restart: always
volumes:
- ./docker/nginx/templates:/etc/nginx/templates:rw,cached
And my default.conf.template
file :
server {
root /var/www/project/public;
listen ${NGINX_PORT};
location / {
# try to serve file directly, fallback to index.php
try_files $uri /index.php$is_args$args;
}
# optionally disable falling back to PHP script for the asset directories;
# nginx will return a 404 error when files are not found instead of passing the
# request to Symfony (improves performance but Symfony's 404 page is not displayed)
# location /bundles {
# try_files $uri =404;
# }
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
# optionally set the value of the environment variables used in the application
# fastcgi_param APP_ENV prod;
# fastcgi_param APP_SECRET <app-secret-id>;
# fastcgi_param DATABASE_URL "mysql://db_user:db_pass@host:3306/db_name";
# When you are using symlinks to link the document root to the
# current version of your application, you should pass the real
# application path instead of the path to the symlink to PHP
# FPM.
# Otherwise, PHP's OPcache may not properly detect changes to
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
# for more information).
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/index.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/project_error.log;
access_log /var/log/nginx/project_access.log;
}
You need to create your file and to copy it in /etc/nginx/templates
.
This file will not be changed by nginx, but the content will be replaced and you should see it in /etc/nginx/conf.d/default.conf
.
You will have in your default.conf
file :
server {
root /var/www/project/public;
listen 80;
location / {
# try to serve file directly, fallback to index.php
try_files $uri /index.php$is_args$args;
}
# optionally disable falling back to PHP script for the asset directories;
# nginx will return a 404 error when files are not found instead of passing the
# request to Symfony (improves performance but Symfony's 404 page is not displayed)
# location /bundles {
# try_files $uri =404;
# }
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
# optionally set the value of the environment variables used in the application
# fastcgi_param APP_ENV prod;
# fastcgi_param APP_SECRET <app-secret-id>;
# fastcgi_param DATABASE_URL "mysql://db_user:db_pass@host:3306/db_name";
# When you are using symlinks to link the document root to the
# current version of your application, you should pass the real
# application path instead of the path to the symlink to PHP
# FPM.
# Otherwise, PHP's OPcache may not properly detect changes to
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
# for more information).
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/index.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/project_error.log;
access_log /var/log/nginx/project_access.log;
}
I hope this helps 😉
~~same problem with 1.9.15-alpine. @abdounikarim may be, that works for the default.conf template, but the issue here is that we want it to work for a custom template.~~
OK, finally that works for me with 1.9.15-alpine :
cseunion-nginx | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh cseunion-nginx | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/default.conf.template to /etc/nginx/conf.d/default.conf cseunion-nginx | 20-envsubst-on-templates.sh: Running envsubst on /etc/nginx/templates/site.conf.template to /etc/nginx/conf.d/site.conf cseunion-nginx | /docker-entrypoint.sh: Configuration complete; ready for start up
Both files gets created. This issue should be considered resolved.
Kind of an old thread but I would like to mention a workaround for parsing environment variables.
None of the entrypoint commands were executing for me (including envsubst
) because I wanted to control my config file with an environment variable
COPY dev-config.nginx.conf /etc/nginx/dev-config.nginx.conf
ENV CONFIG_FILE='/etc/nginx/dev-config.nginx.conf'
CMD nginx -c "${CONFIG_FILE}" -g 'daemon off;'
Based on the very helpful comment from @TamerShlash and the linked table in the Docker docs, this turns the final command into what's below:
/docker-entrypoint.sh /bin/sh -c nginx -c "${CONFIG_FILE}" -g 'daemon off;'
And thus skips the entrypoint since the command is /bin/sh
not nginx
.
The key is that you need to use the array form of CMD. But if you use the array form of CMD, environment variable substitution doesn't work. So the fix is:
Create an executable file called nginx
with these contents:
#!/bin/sh
/usr/sbin/nginx -c "${CONFIG_FILE}" -g 'daemon off;'
/usr/local/bin/nginx
so that it's invoked prior to the other commandsCMD
to just CMD ["nginx"]
The relevant Dockerfile
change looks like:
ADD nginx /usr/local/bin/nginx
CMD ["nginx"]
This turns the final command for the Docker image into:
/docker-entrypoint.sh nginx
But nginx
in this context uses /usr/local/bin/nginx
not /usr/sbin/nginx
. Since /usr/local/bin/nginx
is an sh file, it will do environment substitution in the command. Because the command is nginx
the entrypoint scripts are executed, including the ones for envsubst
.
I am literally stuck with below setup, and I am facing the same issue.
# build stage
FROM node:lts-alpine as build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# production stage
FROM nginx:latest as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY ./entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
My entrypoint file
#!/bin/sh
JSON_STRING='window.configs = { \
"VUE_APP_VARIABLE_1":"'"${VUE_APP_VARIABLE_1}"'", \
"VUE_APP_VARIABLE_2":"'"${VUE_APP_VARIABLE_2}"'" \
}'
sed -i "s@// CONFIGURATIONS_PLACEHOLDER@${JSON_STRING}@" /usr/share/nginx/html/index.html
exec "$@"
vue-app:
container_name: vue-app
image: vue-app
volumes:
- "./nginx/templates/:/etc/nginx/templates/"
environment:
MY_VARIABLE: 'I AM A VARIABLE'
ports:
- 8080:80
restart: on-failure
Hi @power-cut.
You're redefining an entrypoint script, which does the templating and variable substitution for nginx configuration.
"Simply place the entrypoint file inside the folder, and NGINX will execute all scripts within that folder."
COPY docker/entrypoint.sh /docker-entrypoint.d/
RUN chmod +x /docker-entrypoint.d/entrypoint.sh
Hi,
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 :thinking:
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
i have another problem, i defined the operation: COPY ./assets/templates/* /etc/nginx/templates/ in the Dockerfile, after run the container, there exist the tempalte config, and also in the conf.d, but the problem is, when i modified the configuration in /assets/templates, and run the contaienr again, the tempaltes configuration not modified. and also the configuration in the conf.d, i tried many times, but the problem still exist, is there any cache for the template?
According to the documentation, I should be able to provide a template directory and the container will automatically extract and replace environment variables, dropping the resulting files in
/etc/nginx/conf.d/
. I don't see that behavior.Base reproducible case
Given the following files (copied and pasted from the example in the documentation):
docker-compose.yml
:templates/foobar.conf.template
:I then run
docker-compose up
and attach a separate shell to my runningweb
container.From within the container I observe the following:
Thank you for your help and forgive me if I'm missing an obvious step!