So, i have set up a docker swarm and connected a worker on it and deployed a stack with 4 services:
generator, which will be located at the worker node
API & scheduler, both will be located on the manager node
proxy, that will be located on the manager node, accepting requests and redirecting it though the other 3
This is my stack file:
version: "3.7"
services:
generator:
image: musicorum/generator:latest
restart: always
environment:
- 'XXXX=XXXX'
deploy:
resources:
reservations:
memory: 860M
placement:
constraints:
- "node.labels.generator==yes"
ports:
- 5000:5000
networks:
- proxy_ext
- netg
volumes:
- type: bind
source: /home/musicorum/cache
target: /usr/src/app/cache
api:
image: musicorum/api:latest
restart: always
environment:
- 'XXXX=XXXX'
networks:
- proxy_ext
ports:
- 4500:4500
deploy:
placement:
constraints:
- "node.labels.generator!=yes"
scheduler:
image: musicorum/scheduler:latest
restart: always
environment:
- 'XXXX=XXXX'
ports:
- 6500:6500
networks:
- proxy_ext
deploy:
placement:
constraints:
- "node.labels.generator!=yes"
proxy:
image: nginx:latest
restart: always
networks:
- proxy_ext
- netg
ports:
- 80:80
- 443:443
configs:
- source: nginx_4
target: /etc/nginx/conf.d/default.conf
- source: sslcrt
target: /etc/ssl/musicorumapp/ssl.crt
- source: sslkey
target: /etc/ssl/musicorumapp/ssl.key
depends_on:
- scheduler
- api
- generator
deploy:
placement:
constraints:
- "node.labels.generator!=yes"
configs:
nginx_4:
external: true
sslcrt:
external: true
sslkey:
external: true
networks:
proxy_ext:
external: true
netg:
driver: overlay
attachable: true
As you can see, the they are connected on the same network, i even created proxy_ext and netg to double-check the connection, but Nginx give this message when start up:
/docker-entrypoint.sh: Configuration complete; ready for start up
2020/07/07 13:32:17 [emerg] 1#1: host not found in upstream "musicorum_generator" in /etc/nginx/conf.d/default.conf:30
nginx: [emerg] host not found in upstream "musicorum_generator" in /etc/nginx/conf.d/default.conf:30
I don't know why the Nginx, at the manager node, can't reach out to the generator container, at the worker node. If it helps, here's my default.conf:
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/ssl/musicorumapp/ssl.crt;
ssl_certificate_key /etc/ssl/musicorumapp/ssl.key;
server_name api.musicorumapp.com;
location / {
proxy_pass http://musicorum_api:4500/;
}
}
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/ssl/musicorumapp/ssl.crt;
ssl_certificate_key /etc/ssl/musicorumapp/ssl.key;
server_name scheduler.musicorumapp.com;
location / {
proxy_pass http://musicorum_scheduler:6500/;
}
}
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/ssl/musicorumapp/ssl.crt;
ssl_certificate_key /etc/ssl/musicorumapp/ssl.key;
server_name generator.musicorumapp.com;
location / {
proxy_pass http://musicorum_generator:5000/;
}
}
In your default.conf you need to reference the services by their service name. This is the name that the internal DNS will resolve.
server {
listen 80;
listen 443 ssl;
ssl_certificate /etc/ssl/musicorumapp/ssl.crt;
ssl_certificate_key /etc/ssl/musicorumapp/ssl.key;
server_name api.musicorumapp.com;
location / {
proxy_pass http://api:4500/; <------ 'api' is the service name
}
}
You only would need to prefix the name of your stack if the reverse proxy server was running external to your stack's network, but since they are all on the same network, the DNS will resolve the service name alone.
You may also remove the ports: 8000:8000 on all of your apps (except reverse proxy) in your stack yaml file because you want to route traffic through your reverse proxy, not bind the port to the host. This could lead to security vulnerabilities as well. There are no port restrictions within a docker network. If an application is listening on 8000, your reverse proxy can contact it with http://service-name:8000 within the stack's overlay network.
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 an EC2 AWS instance and I want to create a test environment for an application.
All other containers are working properly, but NGINX's is the only one that is not stable and keeps restarting constantly.
I tried in several ways to make NGINX run. Change addresses I used Return 301. Tried to remove certbot, nothing worked.
I'm an intern and I need to create this test environment for an assessment. Can someone help me?
my docker-compose.yml is like this
version: "3.9"
services:
backend:
container_name: backend
image: <my_image>
restart: always
ports:
- "3030:3030"
environment:
- "DATABASE_URL=${DATABASE_URL}"
- "SERVER_PORT=${SERVER_PORT}"
- "JWT_SECRET=${JWT_SECRET}"
sniffer:
container_name: mqtt-sniffer
image: <my_image>
restart: always
environment:
- "POSTGRES_DB=${POSTGRES_DB}"
- "POSTGRES_USER=${POSTGRES_USER}"
- "POSTGRES_PASSWORD=${POSTGRES_PASSWORD}"
- "POSTGRES_HOST=${POSTGRES_HOST}"
- "MQTT_CLIENT_ID=${MQTT_CLIENT_ID}"
- "MQTT_USER=${MQTT_USER}"
- "MQTT_PASSWORD=${MQTT_PASSWORD}"
- "MQTT_HOST=${MQTT_HOST}"
- "MQTT_PORT=${MQTT_PORT}"
web:
container_name: web
image: <my_image>
restart: always
nginx:
container_name: nginx
image: nginx:latest
restart: always
ports:
- "80:80"
- "443:443"
environment:
- API_SERVER_NAME=${API_SERVER_NAME}
volumes:
- /home/ubuntu/app/nginx/default.conf:/etc/nginx/nginx.conf:ro
- /home/ubuntu/app/certbot/www:/etc/nginx/acme_challenge:ro
- /home/ubuntu/app/certbot/certificate:/etc/nginx/certificate:ro
and my default.conf is like this
events {}
http {
server {
listen 80;
listen [::]:80;
server_name 18.231.90.250;
location /.well-known/acme-challenge/ {
root /etc/nginx/acme_challenge;
}
location / {
proxy_pass http://18.231.90.250;
}
}
server {
listen 80;
listen [::]:80;
location /.well-known/acme-challenge/ {
root /etc/nginx/acme_challenge;
}
location / {
proxy_pass http://web:80;
}
}
server {
listen 443 default_server ssl;
listen [::]:443 ssl;
ssl_certificate /etc/nginx/certificate/live/teste.clientautoponia.com/fullchain.pem;
ssl_certificate_key /etc/nginx/certificate/live/teste.clientautoponia.com/privkey.pem;
location / {
proxy_pass http://backend:3030;
}
}
I don't need to have the ssl certificate, I just want to be able to communicate when accessing the instance. Get a 200 when trying to access the address.
I have a project running on docker. I use Nginx reverse proxy to run my app.
All works fine but trying to personalize the server_name on nginx but couldn't figure out how.
Docker yml file
I've added server name to /etc/hosts by docker
version: "3"
services:
nginx:
container_name: nginx
volumes:
- ./nginx/logs/nginx:/var/log/nginx
build:
context: ./nginx
dockerfile: ./Dockerfile
depends_on:
- menu-app
ports:
- "80:80"
- "433:433"
extra_hosts:
- "www.qr-menu.loc:172.18.0.100"
- "www.qr-menu.loc:127.0.0.1"
networks:
default:
ipv4_address: 172.18.0.100
menu-app:
image: menu-app
container_name: menu-app
volumes:
- './menu-app/config:/var/www/config'
- './menu-app/core:/var/www/core'
- './menu-app/ecosystem.json:/var/www/ecosystem.json'
- './menu-app/tsconfig.json:/var/www/tsconfig.json'
- './menu-app/tsconfig-build.json:/var/www/tsconfig-build.json'
- "./menu-app/src:/var/www/src"
- "./menu-app/package.json:/var/www/package.json"
build:
context: .
dockerfile: menu-app/.docker/Dockerfile
tmpfs:
- /var/www/dist
ports:
- "3000:3000"
extra_hosts:
- "www.qr-menu.loc:127.0.0.1"
- "www.qr-menu.loc:172.18.0.100"
networks:
default:
ipam:
driver: default
config:
- subnet: 172.18.0.0/24
And I have Nginx conf
server_names_hash_bucket_size 1024;
upstream local_pwa {
server menu-app:3000;
keepalive 8;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name www.qr-menu.loc 172.18.0.100;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://local_pwa/;
}
}
but unfortunately, app runs on localhost instead of www.qr-menu.loc
I couldn't figure out how to change server_name on Nginx.
This is a really, really late answer. The server_name directive tells nginx which configuration block to use on receipt of a request. Also see: http://nginx.org/en/docs/http/server_names.html
I think the docker-compose extra_hosts directive might only work for domain-name resolution within the docker network. In other words, on your computer that's running docker the name "www.qr-menu.loc" is not available, but in a running docker container that name should be available.
I have a docker-compose.yml as follows setup at my root. For context, I have a Ghost CMS blog hosted on a Digital Ocean droplet. I want to install Commento using Docker (an open source commenting solution), but as I'm routing my traffic through Cloudflare DNS, I require SSL on both the server side and the frontend side.
However, I installed Ghost through Digital Ocean's one click Ghost setup, which configured nginx to be the reverse proxy for my site. Nginx is NOT in the container (installed on server). Nginx listens on port 80 and 443. When I try docker-compose up, it says the following error:
Error starting userland proxy: listen tcp 0.0.0.0:443: bind: address already in use
Traefik cannot listen on the same ports at nginx (which is not within the container, but installed on the server itself). How can I fix this problem, and have my commento server reverse proxied through SSL as well? My docker-compose is as below:
version: '3.7'
services:
proxy:
restart: always
image: traefik
command:
- "--api"
- "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https"
- "--entrypoints=Name:https Address::443 TLS"
- "--defaultentrypoints=http,https"
- "--acme"
- "--acme.storage=/etc/traefik/acme/acme.json"
- "--acme.entryPoint=https"
- "--acme.httpChallenge.entryPoint=http"
- "--acme.onHostRule=true"
- "--acme.onDemand=false"
- "--acme.email=changeme#example.com" # TODO: Replace with your email address
- "--docker"
- "--docker.watch"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik/acme:/etc/traefik/acme
networks:
- web
ports:
- "80:80"
- "443:443"
labels:
- "traefik.enable=false"
server:
image: registry.gitlab.com/commento/commento:latest
ports:
- 8080:8080
environment:
COMMENTO_ORIGIN: https://commento.example.com # TODO: Replace commento.example.com with your domami$ COMMENTO_PORT: 8080
COMMENTO_POSTGRES: postgres://postgres:passwordexample#db:5432/commento?s$
depends_on:
- db
networks:
- db_network
- web
db:
image: postgres
environment:
POSTGRES_DB: commento
POSTGRES_USER: postgres
POSTGRES_PASSWORD: examplepassword #TODO: Replace STRONG_PASSWORD with th$ networks:
- db_network
volumes:
- postgres_data_volume:/var/lib/postgresql/data
volumes:
postgres_data_volume:
networks:
web:
external
db_network:
Here is my nginx server config under available sites:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com;
root /var/www/ghost/system/nginx-root; # Used for acme.sh SSL verification (https://acme.sh)
ssl_certificate /etc/letsencrypt/example.com/fullchain.cer;
ssl_certificate_key /etc/letsencrypt/example.com/example.com.key;
include /etc/nginx/snippets/ssl-params.conf;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:2368;
}
location ~ /.well-known {
allow all;
}
client_max_body_size 50m;
}
Sorry, kind of new to this. Thank you!
docker-compose.yml
...
ports:
- "80:80"
- "443:443"
...
nginx/conf
...
listen 443 ssl http2;
listen [::]:443 ssl http2;
...
Nginx used HOST port 443, so you cannot reuse it on your docker-compose, you must another one that is free.
I have set up a web application in docker which is currently running internal to the host at 172.19.0.3:8888. I want this web application accessible over the internet on port 443 (https), with requests to port 80 (HTTP) redirected to 443.
I plan to use an Nginx reverse proxy in a docker container to achieve this, but I do not know how to properly configure it to point at the docker container 172.19.0.3:8888. Accessing http://172.19.0.3:8888 from the host works.
Here is the guide I tried to follow, but it just didn't show how to point at a docker container specifically.
https://medium.com/#pentacent/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71
Note
If I set the port 443 proxy_pass to http://example.org, it works. So Cert configurations are working correctly.
Web application
Running on 172.19.0.3:8888 internal to the host
docker-compose for Nginx and Certbot
My certs are coming back clean.
version: '3'
services:
nginx:
image: nginx:1.15-alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./Volumes/nginx:/etc/nginx/conf.d
- ./Volumes/certbot/conf:/etc/letsencrypt
- ./Volumes/certbot/www:/var/www/certbot
certbot:
image: certbot/certbot
volumes:
- ./Volumes/certbot/conf:/etc/letsencrypt
- ./Volumes/certbot/www:/var/www/certbot
Nginx app.conf
server {
listen 80;
server_name forums.example.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name forums.example.com;
ssl_certificate /etc/letsencrypt/live/forums.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/forums.example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://172.19.0.3:8888/;
}
}
Web Application
flarum:
image: mondedie/docker-flarum:0.1.0-beta.8.1-stable
container_name: flarum
env_file:
- ./flarum.env
volumes:
- ./Volumes/assets:/flarum/app/public/assets
- ./Volumes/extensions:/flarum/app/extensions
- ./Volumes/nginx:/etc/nginx/conf.d
depends_on:
- mariadb
mariadb:
image: mariadb:10.2
container_name: mariadb
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=flarum
- MYSQL_USER=flarum
- MYSQL_PASSWORD=password
volumes:
- ./Volumes/mysql/db:/var/lib/mysql
Docker Compose creates a seprate network for docker-compose.yaml file.
So you can add your web application as service (eg: webapp) in current compose file. And in nginx.conf directly point to your service. Rather than using IP you can use the service name as DNS which will resolve by Docker for the same network.
location / {
proxy_pass http://webapp:8888/;
}