I want to run Nginx as static file server behind Traefik reverse proxy using Docker (docker-compose).
docker-compose.yml
version: '3.8'
services:
traefik:
image: traefik
command:
- --entrypoints.web.address=:80
- --providers.docker
- --providers.docker.exposedbydefault=false
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
nginx:
build: ./docker/dev/nginx/.
labels:
- traefik.enable=true
- traefik.http.routers.nginx.entrypoints=web
- traefik.http.routers.nginx.rule=PathPrefix(`/static`) || PathPrefix(`/media`) || Path(`/robots.txt`) || Path(`/favicon.ico`)
- traefik.http.services.nginx.loadbalancer.server.port=80
nginx.conf
server {
listen 80;
listen [::]:80;
...
}
And it works,
But when I try to change internal nginx port to another, lets say 8082, Traefik returns 502 error and prints '502 Bad Gateway' caused by: dial tcp 172.21.0.6:8082: connect: connection refused" in debug logs.
By changing port I mean:
replacing traefik.http.services.nginx.loadbalancer.server.port=80 with traefik.http.services.nginx.loadbalancer.server.port=8082 in docker-compose.yml
replacing listen 80; listen [::]:80; with listen 8082; listen [::]:8082; in nginx.conf
I have other apps in config, like Django running on gunicorn server. There is no problem for gunicorn to listen on 3000 port, and for Traefik to forward incoming :80 requests to :3000.
Why doesn't it work with nginx?
You have told nginx to listen to 8082 port which is ok, but the container has to expose the port. (I guess by default the container expose 80 port)
You seem to have a custom nginx image, so you can add/replace the EXPOSE keyword in your image to have something like this : EXPOSE 8082.
You have to build and restart the container for the change to take effect, then you can check the exposed ports with docker-compose ps.
Related
I have a some issue when trying to deploy a simple FastAPI application with Nginx on Google Cloud Platform. In my case I should use SSH-terminal to run Docker container with Nginx and FastAPI. My nginx.conf configuration looks like:
access_log /var/log/nginx/app.log;
error_log /var/log/nginx/app.log;
server {
server_name example.com;
listen 80;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /root/ssl/cert.pem;
ssl_certificate_key /root/ssl/key.pem;
location / {
proxy_pass "http://example.com:8004/";
}
}
And my docker-compose.yml looks like:
version: '3.8'
services:
nginx-proxy:
image: nginx
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx:/etc/nginx/conf.d
- ./ssl/cert1.pem:/root/ssl/cert.pem
- ./ssl/privkey1.pem:/root/ssl/key.pem
- ./ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem
web:
environment: [.env]
build: ./project
ports:
- 8004:8000
command: gunicorn main:app -k uvicorn.workers.UvicornWorker -w 2 -b 0.0.0.0:8000
volumes:
- ./project:/usr/src/app
networks:
default:
external:
name: nginx-proxy
Also, I have a Google Cloud VM instance with Firewall HTTP, HTTPS traffic On option, and additionally configured Firewall with rules allowed TCP connections over 443 and 80 ports (Domain name is provided by Google Cloud also, and redirects to VM's external IP address when I put it in my browser address field).
I run my docker-image from SSH-terminal with docker-compose up --build, then I get 502 Bad Gateway Nginx error in my browser (after going to example.com). I would like to know whether it is possible to run the docker image this way from inside SSH-terminal, as well as which steps did I miss to do it the right way?
I have tried this:
NGINX reverse proxy not working to other docker container
and this:
Docker nginx-proxy : proxy between containers
and followed nginx config from here:
nginx proxy_pass to a linked docker container
I am simply trying to tell nginx to proxy to a linked api service on port 4000. I do not want to expose 4000 to host machine because there will be multiple services running on this port.
This is my docker-compose.yml:
version: '3'
services:
api:
build: ./api
image: myapi:latest
container_nameE: api
api_nginx:
image: nginx:latest
container_name: api_nginx
depends_on:
- api
links:
- api
ports:
- "80:80"
environment:
- NGINX_SERVER_NAME:localhost
volumes:
- ./nginx:/etc/nginx/conf.d
...
...
and my nginx server is super minimal:
upstream backend {
server api;
}
server {
listen 80;
listen [::]:80;
server_name ${NGINX_SERVEE_NAME};
location / {
resolver 127.0.0.1;
proxy_pass http://backend/$1;
}
}
This is the error is throwing:
...[error] 20#20: *1 no resolver defined to resolve api, client: 172.23.0.1, server: ${nginx_server_name}....
and the page shows a 502 Bad Gateway
What is going on? I've followed other people's nginx configs and it's not working, I have no idea.
I understand how docker-composer map ports, but what does it mean when a config file map two different port couples, as seen in the following example?
web:
image: nginx
ports:
- "80:80"
- "443:443"
Config sample was taken from php7-dockerized repo.
It means that for your web service, nginx container has port 80 open and can be accessed from the outside world on port 80 and also has port 443 open and can be accessed from the outside on port 443.
Here the mapping is on the same port. But you can have for exemple:
web:
image: nginx
ports:
- "8080:80"
Here the ports are not the same anymore. It means that
in order to access your service from the outside world, you would have to visit let say localhost:8080 on your machine.
But for nginx running inside of the container, the port to listen to is port 80, so it would be port 80 that would be inside your nginx.conf file:
server {
listen 80;
...
Is it possible to run docker image on other host than localhost?
Ports 80 and 443 are always occupied by other applications, so I was wondering if it's possible to run it on, e.g. 192.168.0.100, and then set up the /etc/hosts file to assign a name for that IP address.
I was trying to set up extra_hosts option, but I'm not sure if it's meant for that. Either way, I did not succeed with setting it up as there was some issue with Value should be a mapping, not an array.
I guess it's worth mentioning that I'm on macOS using docker-compose to run everything. Thank you in advance.
docker-compose.yaml
version: "2"
services:
php:
build: ./php
volumes:
- ../develog.org:/usr/share/nginx/html
depends_on:
- memcached
nginx:
build: ./nginx
ports:
- 4001:80
- 4002:443
volumes_from:
- php:ro
depends_on:
- php
memcached:
image: memcached:alpine
networks:
default:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.1.0.0/16
nginx configuration
map $scheme $ssl_request {
https "https";
}
server {
# support http and ipv6
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
# support https and ipv6
listen 443 default_server ssl;
listen [::]:443 ipv6only=on default_server ssl;
# path to web directory
root /web/;
index index.html index.htm;
# domain or subdomain
server_name localhost;
include self-signed.conf;
include ssl-params.conf;
}
Why not use a different port when running your image? (unless you have to use port 80/443)
So, for example, if you are running a webserver image like Apache httpd, which normally runs on port 80 use:
docker run -p 127.0.0.1:8080:80/tcp httpd
Then you can just use port 8080 on localhost.
For docker-compose add a ports section to the docker-compose.yaml file. E.g.
image: <image>
ports:
- "8080:80"
The actual ports/image would depend on which image you are using.
See https://docs.docker.com/compose/compose-file/#ports for details.
I have an two containers running via docker-compose:
version: '3'
services:
web:
image: me/web
container_name: web
nginx:
image: me/nginx
container_name: nginx
ports:
- '80:80'
volumes:
- ../nginx:/etc/myapp/nginx
My nginx container copies in a new default.conf from the mapped volume from the entrypoint.sh:
#!/usr/bin/env bash
cp /etc/myapp/nginx/default.conf /etc/nginx/conf.d/default.conf
nginx -g 'daemon off;'
My custom default.conf looks like:
server {
listen 80;
server_name my.website.com;
location / {
proxy_pass http://web/;
}
}
With this configuration everything works as expected. After starting with docker-compose I can then navigate to http://my.website.com and access the web container instance properly.
However, now I want to change my port to something other than the default 80, such as 81 for example:
services:
..
nginx:
image: me/nginx
container_name: nginx
ports:
- '81:80'
..
Now this no longer works. Whenever I visit http://my.website.com:81 I get:
This site can’t be reached
my.website.com refused to connect.
ERR_CONNECTION_REFUSED
The other weird part is that if I use localhost rather than my.website.com, everything works just fine on port 81. Ex:
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://web/;
}
}
Navigating to http://localhost:81 works correctly.
What am I doing wrong here? How do I configure nginx to something other than localhost (my domain) and proxy on a different port than 80 to my web container?
Check that port 81 is open on my.website.com i.e. check firewall rules are in place etc