I'm creating an application with docker-compose, vue.js, and phoenix/elixir. So far the phoenix application will work on localhost, but will not work when I run the application using docker-compose + NGINX and it's been difficult to debug. Any advice or suggestions would be helpful. The phoenix application itself does not have any of the configuration options changed from the "hello world" application and only adds in socket functionality for a chat room.
Here is the docker-compose file:
version: "3.9"
networks:
main_network:
volumes:
volume1:
varwwwcertbot:
certbotconf:
data_volume:
services:
phx:
build:
context: ./phx
restart: always
volumes:
- ./phx:/phx
ports:
- "4000:4000"
depends_on:
db:
condition: service_healthy
networks:
- main_network
db:
image: postgres
restart: always
volumes:
- ./docker-entrypoint-initdb.d/init.sql:/docker-entrypoint-initdb.d/init.sql
- data_volume:/var/lib/postgresql/data
environment:
- POSTGRES_NAME=dev-postgres
- POSTGRES_USER=pixel
- POSTGRES_DATABASE=lightchan
- POSTGRES_PASSWORD=exploration
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U pixel"]
interval: 5s
timeout: 5s
retries: 20
networks:
- main_network
frontend:
build:
context: ./frontend
restart: always
volumes:
- './frontend:/app'
- '/app/node_modules'
ports:
- "3000:3000"
networks:
- main_network
depends_on:
- "phx"
nginx:
build:
context: ./nginx
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- volume1:/usr/share/nginx/html
- varwwwcertbot:/var/www/certbot
- certbotconf:/etc/letsencrypt
networks:
- main_network
certbot:
image: certbot/certbot:latest
volumes:
- varwwwcertbot:/var/www/certbot
- certbotconf:/etc/letsencrypt
networks:
- main_network
Here is the nginx file:
events{
}
http{
map $http_upgrade $connection_upgrade {
default Upgrade;
'' close;
}
upstream websocket {
server 164.92.157.124:4000;
}
server {
listen 80;
server_name localhost lightchan.org www.lightchan.org;
root /usr/share/nginx/html;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
if ($scheme = http) {
return 301 https://lightchan.org$request_uri;
}
}
server {
listen 443 default_server ssl http2;
listen [::]:443 ssl http2;
server_name localhost lightchan.org www.lightchan.org;
ssl_certificate /etc/letsencrypt/live/lightchan.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/lightchan.org/privkey.pem;
location /media/pics/ {
autoindex on;
}
location / {
proxy_pass http://frontend:3000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_intercept_errors on;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location ^~ /socket/ {
proxy_pass http://websocket;
add_header X-uri "$uri";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
}
location ^~ /api/ {
proxy_pass http://phx:4000;
add_header X-uri "$uri";
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "upgrade";
}
}
}
Note here that I attempted to proxy through an upstream for a /socket/ config and also attempted to use /api/ just using the phx docker tag. Both frontend and phx are linked in the docker-compose file, so they should be coming through. I've also turned on the 'upgrade' feature of Connection so this should be forwarding websockets too.
The phoenix application itself, still has the / front page uri, so I would suspect that being able to navigate to either www.lightchan.org/api or www.lightchan.org/socket would then allow me to see the phoenix hello world splash page, but instead there's a 502 error.
Any suggestions?
EDIT:
I've edited config/config.exs in the phoenix application to run on host 127.0.0.1 like this:
# Configures the endpoint
config :my_app, MyAppWeb.Endpoint,
url: [host: "127.0.0.1"],
render_errors: [view: MyAppWeb.ErrorView, accepts: ~w(html json), layout: false],
pubsub_server: MyApp.PubSub,
live_view: [signing_salt: "blah"]
and tested this running on locally, and it works, correctly showing the splash page at /. I've attempted to get this to work using http://<SERVER IP>:4000 on my server, but no luck.
EDIT EDIT:
Frustratingly, my autoindex for /media/pics is not working, but rather routing to the the frontend. Here is an embarrassingly thorough guide on routing priorities in NGINX (Guide on how to use regex in Nginx location block section?) and here (Nginx location priority). According to the second link:
location ^~ /images/ {
# matches any query beginning with /images/ and halts searching,
# so regular expressions will not be checked.
[ configuration D ]
}
should mean that
location ^~ /media/pics/ {
autoindex on;
}
location / {
<...>
should stop searching and the return an autoindex. So https://www.lightchan.org/media/pics/myimage.png should return myimage.png. That doesn't work and neither does
location /media/pics/ {
autoindex on;
}
Although I could have sworn it was working before...hmm.
Thanks to GreenMachine on Discord the answer was found here:
https://dev.to/eikooc/using-docker-for-your-elixir-phoenix-application-n8n
change dev.exs in config:
# from this:
http: [ip: {127, 0, 0, 1}, port: 4000],
# to this:
http: [ip: {0, 0, 0, 0}, port: 4000],
Related
I want to call my api point in my react application. Here when I access the localhost then my react app opens up but all the api points doest work when I hit "localhost/apipoint". this shows me 404 not found or 502 bad request.
Here is my docker-compose file
version: "3.8"
services:
nodeserver:
build:
context: ./Backend
networks:
- app-network
ports:
- "8082:8082"
frontend:
build:
context: ./Frontend
networks:
- app-network
ports:
- "80:80"
networks:
app-network:
my nginx default.conf
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location /apipoint {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:8082;
}
location / {
# root /usr/share/nginx/html;
root /var/www/html;
}
}
I've tried a few different examples online. It seems like no matter what I do, I get a "this site can't be reached" when I type in http://example.com or http://www.example.com.
I must have something misconfigured somewhere. Https is working just fine.
user nginx;
events {
worker_connections 1000;
}
http {
upstream web-api {
server web:80;
}
server {
listen 80;
server_name *.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /etc/nginx/certs/www_example_com.crt;
ssl_certificate_key /etc/nginx/certs/example.key;
location / {
proxy_pass http://web-api;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
version: '3.7'
services:
web:
image: 'exampleimage'
container_name: 'examplecontainer'
ports:
- '5000:80'
restart: always
reverseproxy:
image: nginx:alpine
volumes:
- ./data/certs:/etc/nginx/certs
- ./nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- '80:80'
- '443:443'
depends_on:
- web
restart: always
thanks for taking the time to read this. I am trying to deploy my application to an AWS EC2 Instance using docker-compose. When i run the command docker-compose up and visit the site, I get an error from nginx saying the below error. I understand that nginx is receiving the request but is unable to find an upstream connection to my react app, and would appreciate any help in correctly configuring the ports/settings.
Error
2 connect() failed (111: Connection refused) while connecting to upstream, client: 108.212.77.70 server: example.com, request: "GET / HTTP/1.1", upstream: "http://172.29.0.4:8003/", host: "example.com"
Here is my nginx default config
upstream meetup_ws {
server channels:8001;
}
upstream meetup_backend {
server backend:8000;
}
upstream meetup_frontend {
server frontend:8003;
}
server {
listen 0.0.0.0:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com example.com;
root /var/www/frontend;
index index.html;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
add_header Strict-Transport-Security "max-age=31536000";
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://meetup_frontend;
}
location /api {
try_files $uri #proxy_api;
}
location #proxy_api {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://meetup_backend;
}
location /ws {
try_files $uri #proxy_websocket;
}
location #proxy_websocket {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://meetup_ws;
}
}
And this is my docker-compose.yml
version: '3'
services:
nginx:
build: ./nginx
restart: always
ports:
- 80:80
- 443:443
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- ./frontend/build:/var/www/frontend
- ./nginx/certs:/etc/nginx/certs
depends_on:
- channels
db:
image: postgres:12.0-alpine
ports:
- 5432:5432
environment:
- POSTGRES_USER=postgres
- POSTGRES_HOST=db
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data/
backend: &backend
build: ./backend
volumes:
- ./backend:/app
ports:
- 8000:8000
command: ["python", "manage.py", "runserver"]
env_file:
- ./.env
depends_on:
- db
- redis
frontend:
build: ./frontend
volumes:
- ./frontend:/app
- node_modules:/app/node_modules
ports:
- 8003:8003
command: npm start
stdin_open: true
redis:
image: "redis:5.0.7"
worker_channels:
<<: *backend
command: ["python", "manage.py", "runworker", "channels"]
depends_on:
- db
- redis
ports:
- 8002:8002
channels:
<<: *backend
command: daphne -b 0.0.0.0 -p 8001 backend.asgi:application
ports:
- 8001:8001
depends_on:
- db
- redis
volumes:
node_modules:
postgres_data:
It is a bit embarrassing why the issue existed but I was able to solve the issue. I did
ping frontend in my nginx container and it was successfully pinging the frontend container. Next I did curl -L http://frontend:8003 and it said curl: (7) Failed to connect to frontend port 8003: Connection refused. I went to the frontend container and did netstat -tulpn and it listed 3000 as the port that was exposed. I check my .env file and it was missing port=8003. Nginx was able to connect upstream afterwards.
I have a simple app of 3 containers which all run in the same AWS EC2 server. I want to configure Nginx to act as a reverse-proxy however I'm pretty new with Nginx and don't know how to set the conf file correctly.
Here is my docker-compose:
version: "3"
services:
nginx:
container_name: nginx
image: nginx:latest
ports:
- "80:80"
volumes:
- ./conf/nginx.conf:/etc/nginx/nginx.conf
frontend:
container_name: frontend
image: myfrontend:image
ports:
- "3000:3000"
backend:
container_name: backend
depends_on:
- db
environment:
DB_HOST: db
image: mybackend:image
ports:
- "8400:8400"
db:
container_name: mongodb
environment:
MONGO_INITDB_DATABASE: myDB
image: mongo:latest
ports:
- "27017:27017"
volumes:
- ./initialization/db:/docker-entrypoint-initdb.d
- db-volume:/data/db
volumes:
db-volume:
The backend fetches data from the database and sends it to be presented by the frontend.
Here is my nginx.conf file:
events {
worker_connections 4096;
}
http {
server {
listen 80;
listen [::]:80;
server_name myDomainName.com;
location / {
proxy_pass http://frontend:3000/;
proxy_set_header Host $host;
}
location / {
proxy_pass http://backend:8400/;
proxy_pass_request_headers on;
}
}
}
How can I set nginx to serve the frontend and backend containers?
You can use the below Nginx configs to solve your issue
events {
worker_connections 4096;
}
http {
server {
listen 80 default_server;
server_name frontend.*;
location / {
resolver 127.0.0.11 ipv6=off;
set $target http://frontend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass $target;
}
}
server {
listen 80;
server_name backend.*;
location / {
resolver 127.0.0.11 ipv6=off;
set $target http://backend:8400;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass $target;
}
}
}
Nginx will be serving the backend and frontend on different domain names, with the below, etc hosts you will be able to get access to the services on the defined domain names
127.0.0.1 backend.me frontend.me
I've published my API, ID server STS and web ui on separate docker containers and I'm using a nginx container to act as the reverse proxy to serve these app. I can browse to each one of them and even open the discovery endpoint for the STS. Problem comes when I try to login into the web portal, it tries to redirect me back to the STS for logging in but I'm getting ERR_CONNECTION_REFUSED the url looks okay I think it's the STS that is not available from the redirection from the Web UI.
My docker-compose is as below:
version: '3.4'
services:
reverseproxy:
container_name: reverseproxy
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
- ./proxy.conf:/etc/nginx/proxy.conf
- ./cert:/etc/nginx
ports:
- 8080:8080
- 8081:8081
- 8082:8082
- 443:443
restart: always
links:
- sts
sts:
container_name: sts
image: idsvrsts:latest
links:
- localdb
expose:
- "8080"
kernel:
container_name: kernel
image: kernel_api:latest
depends_on:
- localdb
links:
- localdb
portal:
container_name: portal
image: webportal:latest
environment:
- TZ=Europe/Moscow
depends_on:
- localdb
- sts
- kernel
- reverseproxy
localdb:
image: mcr.microsoft.com/mssql/server
container_name: localdb
environment:
- 'MSSQL_SA_PASSWORD=password'
- 'ACCEPT_EULA=Y'
- TZ=Europe/Moscow
ports:
- "1433:1433"
volumes:
- "sqldatabasevolume:/var/opt/mssql/data/"
volumes:
sqldata:
And this is the nginx.config:
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
upstream docker-sts {
server sts:8080;
}
upstream docker-kernel {
server kernel:8081;
}
upstream docker-portal {
server portal:8081;
}
ssl_ciphers EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_certificate cert.pem;
ssl_certificate_key key.pem;
ssl_password_file global.pass;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_cache_bypass $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Proto $scheme;
server {
listen 8080;
listen [::]:8080;
server_name sts;
location / {
proxy_pass http://docker-sts;
# proxy_redirect off;
}
}
server {
listen 8081;
listen [::]:8081;
server_name kernel;
location / {
proxy_pass http://docker-kernel;
}
}
server {
listen 8082;
listen [::]:8082;
server_name portal;
location / {
proxy_pass http://docker-portal;
}
}
}
The web ui redirects to the below url, which works okay if I browse to it using the STS server without nginx.
http://localhost/connect/authorize?client_id=myclient.id&redirect_uri=http%3A%2F%2Flocalhost%3A22983%2Fstatic%2Fcallback.html&response_type=id_token%20token&scope=openid%20profile%20kernel.api&state=f919149753884cb1b8f2b907265dfb8f&nonce=77806d692a874244bdbb12db5be40735
Found the issue. The containers could not see each other because nginx was not appending the port on the url.
I changed this:
'proxy_set_header Host $host;'
To this:
'proxy_set_header Host $host:$server_port;'