Context
I am trying to build out a local development environment and I am struggling to get it to work. I want docker and docker compose to run nginx as a reverse proxy and a postgresql database
Project Structure
my-app/
├─ server/ (fastify node server)
├─ client/ (sveltekit dev server)
├─ nginx/
│ ├─ Dockerfile
│ ├─ default.conf
├─ docker-compose.yml
I want the only prerequisites to be Node, git and docker. I to be able to clone the project, start docker compose, and then start the two projects individually
Prior Research
I've read through the nginx Beginners guide and several pieces of the nginx documentation but I find their docs fairly unapproachable. I also have found several guides that have my client and server running inside docker containers and set up as separate services within docker compose. That is not the end goal, but unfortunately I have not gotten those to work either.
This question seems close and I found it helpful. But it’s still not working.
To start, I'm just trying to get everything to work on http://localhost:4000 in order to remove some of the complexity
This is my best attempt thus far:
##########################
# docker-compose.yml
##########################
version: '3.9'
services:
reverse-proxy:
build: ./nginx
ports:
- 8080:8080
##########################
# nginx/Dockerfile
##########################
FROM nginx:1.21.3
COPY ./default.conf /etc/nginx/conf.d/default.conf/
##########################
# nginx/default.conf
##########################
server {
listen 8080;
location / {
proxy_pass http://host.docker.internal:8080;
}
location /api/ {
proxy_pass http://host.docker.internal:3000;
}
}
With this set up, I can hit http://localhost:3000/api/ and get my json response from the server, but when I try and hit http://localhost:8080/api/, I get the standard nginx 502 response and nginx does not successfully reach my node server. The nginx logs give me this error:
2021/11/16 12:38:39 [error] 34#34: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.19.0.1, server: , request: "GET /api/ HTTP/1.1", upstream: "http://192.168.65.2:3000/api/", host: "localhost:8080"
I don't know where the IP address comes from up above, but if I hit http://192.168.65.2:3000/api/ locally, then the browser just spins and spins.
End Goal
I am looking for a properly configured docker-compose.yml
and a single, relatively simple nginx file for the moment that gets mapped into the default. HTTPS and a custom URL are really later problems. For now, I just want to be able to hit my nginx reverse proxy within a docker container and properly route to my two locally running node servers (one an API server and one a sveltekit dev server - neither inside docker containers).
Thank you in advance for any help!
CodePudding user response:
There a couple of things you have to keep in mind:
- Docker compose by default uses the service name as hostname for inter container networking
- Nginx need to know the upstream first
- You don't need Nginx in a Dockerfile, use it directly in
docker-compose.yml
instead. And mount your config file into the container. - You need to dockerize your front-end and back-end to connect them to nginx
An example repo where I use nginx, docker and docker-compose: https://gitlab.com/datails/api .
Example default.conf
:
upstream api_server {
server api:3000;
}
upstream frontend {
server frontend:3000;
}
server {
listen 80;
location /api {
proxy_pass http://api_server;
}
location / {
proxy_pass http://frontend/;
}
}
Example docker-compose.yml
version: '3.8'
services:
nginx:
image: nginx:1.19.4
depends_on:
- server
- frontend
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf
ports:
- '8080:80'
Then make sure you have your front-end dockerized and called frontend
as a service in your docker-compose like:
version: '3.8'
services:
nginx:
image: nginx:1.19.4
depends_on:
- server
- frontend
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
ports:
- '8080:80'
frontend:
build: ./frontend
command: npm run start
volumes:
- ./frontend/src:/home/usr/app/src
api:
build: ./api
command: npm run start
volumes:
- ./api/src:/home/usr/app/src
Note you don't need a port because you use inter container communication.