Docker nginx proxy to host
Configure nginx like the following (make sure you replace IP of Docker Host) and save it as default.conf
:
server { listen 80; server_name _; location / { proxy_pass http://<IP of Docker Host>; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; }}
Now bring up the container:
docker run -d --name nginx -p 80:80 -v /path/to/nginx/config/default.conf:/etc/nginx/conf.d/default.conf nginx
If you are using Docker Compose file version 3 you don't need any special config for docker-compose.yml
file at all, just use the special DNS name host.docker.internal
to reach a host service, as on the following nginx.conf
example:
events { worker_connections 1024;}http { upstream host_service { server host.docker.internal:2345; } server { listen 80; access_log /var/log/nginx/http_access.log combined; error_log /var/log/nginx/http_error.log; location / { proxy_pass http://host_service; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $realip_remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_http_version 1.1; proxy_set_header Connection ""; } } }
Solution 1
Use network_mode: host
, this will bind your nginx instance to host's network interface. This could result in conflicts when running multiple nginx containers: every exposed port is binded to host's interface.
Solution 2
I'm running more nginx instances for every service I would like expose to outside world. To keep the nginx configurations simple and avoid binding every nginx to host use the container structure:
dockerhost
- a dummy container with network_mode: host
proxy
- nginx container used as a proxy to host service,
link dockerhost
to proxy
, this will add an /etc/hosts
entry in proxy
contianer - we can use 'dockerhost' as a hostname in nginx configuration.
docker-compose.yaml
version: '3'services: dockerhost: image: alpine entrypoint: /bin/sh -c "tail -f /dev/null" network_mode: host proxy: image: nginx:alpine links: - dockerhost:dockerhost ports: - "18080:80" volumes: - /share/Container/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
default.conf
location / { proxy_pass http://dockerhost:8080;
This method allows us to have have automated let's encrtypt certificates generated for every service running on my server. If interested I can post a gist about the solution.