Opened 10 years ago
Last modified 9 years ago
#658 new enhancement
Implement new type of "resolver" -- "system" [for Docker usage]
Reported by: | Артём Скорецкий | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-core | Version: | 1.7.x |
Keywords: | docker dns resolve system | Cc: | |
uname -a: | Linux 2b5fbf195b05 3.16.4-tinycore64 #1 SMP Thu Oct 23 16:14:24 UTC 2014 x86_64 GNU/Linux | ||
nginx -V: |
nginx version: nginx/1.7.7
built by gcc 4.7.2 (Debian 4.7.2-5) TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-http_spdy_module --with-cc-opt='-g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,--as-needed' --with-ipv6 |
Description
It would be great if I could use "system" resolver for converting DNS name into IP. That would make usage of nginx inside Docker way easier.
When you use dynamic resolving (see example below) you have to set up your DNS server IP by "resolver" parameter.
It is fine for the most of the cases but in some setups (e.g with Docker) you don't have a dedicated DNS server but have resolving configured on your machine (using /etc/hosts, /etc/resolv and so one). Yes, my DNS names are not public, so I cannot use 8.8.8.8 or whatever public DNS.
That brings us to idea to use the same nginx code that does static resolving on nginx.conf parsing -- the one that is using system function to resolve it.
Since you already have dynamic name resolving (so you solved all surrounding issues like non-blocking resolving, etc.) it seems to be a minor change to use another function for resolving.
My current config (not valid!):
server { listen 80; server_name ~(?P<project>[^.]+)\.localhost$; location / { proxy_pass http://$project:8000; } }
All projects have entry in /etc/hosts generated by Docker on run.
Ideal solution:
server { listen 80; server_name ~(?P<project>[^.]+)\.localhost$; resolver system; # here is the trick location / { proxy_pass http://$project:8000; } }
Change History (5)
comment:1 by , 10 years ago
comment:2 by , 10 years ago
Actually, the right and optimal way to solve your problem would be generating nginx configuration and thus avoiding dynamic resolving.
comment:3 by , 10 years ago
And there's also a Docker image that does exactly that: https://github.com/jwilder/nginx-proxy.
comment:4 by , 10 years ago
I didn't say it is impossible now -- you could still generate nginx config on fly or install lightweight DNS server (e.g. dnsmasq) locally.
Still I find this topic pretty demanded feature -- while googling I found it was one of common misunderstanding / feature lacking -- that you cannot use system resolving dynamically.
Don't get me wrong -- this solution may be not finely efficient (though I don't see much difference with current dynamic resolving -- especially while we cache it) -- but it allows you to solve some tasks in more simple and straightforward way. And sure, for high-load you would need some another solution.
Replying to Valentin V. Bartenev:
It solved by implementing our own asynchronous resolver. Since the system's resolver is blocking,
it can't be used for dynamic name resolution.
Is it possible to wrap system's resolver into async function?
Or maybe at least include an option to read /etc/hosts before trying out given DNS server? That would be best in matter of time_spend/results ratio.
comment:5 by , 9 years ago
Heres a workaround for people using Docker.
export NAMESERVER=`cat /etc/resolv.conf | grep "nameserver" | awk '{print $2}' | tr '\n' ' '`
What this does is take all the nameserver
entries from /etc/resolv.conf
and print them in a line, so you can use them with nginx's resolver
directive.
Your Dockerfile will need to have a custom script for the entrypoint that generates the config file and then starts nginx.
Lets say you have a file called nginx.conf.template
that looks something like:
...snip... http { server { resolver $NAMESERVER valid=10s; ...snip.... } } }
Your startup script can then use the envsubst
program to generate an nginx.conf and then start nginx. eg:
#!/bin/bash if [ "$NAMESERVER" == "" ]; then export NAMESERVER=`cat /etc/resolv.conf | grep "nameserver" | awk '{print $2}' | tr '\n' ' '` fi echo "Nameserver is: $NAMESERVER" echo "Copying nginx config" envsubst '$NAMESERVER' < /nginx.conf.template > /nginx.conf echo "Using nginx config:" cat /nginx.conf echo "Starting nginx" nginx -c /nginx.conf -g "daemon off;"
It solved by implementing our own asynchronous resolver. Since the system's resolver is blocking, it can't be used for dynamic name resolution.