I use Swarmpit to control Swarm nodes.
There are multiple stacks on Swarm (one for each application) and another stack with NGINX. All the stacks are attached to one external
docker network named "public".
The web applications is a Laravel application (Octane) serverd on port 9000 (It is reachable from IP:9000).
NGINX is reachable on port 80
I need to serve all the apps through NGINX.
Web Application docker-compose.yml
version: '3.3'
services:
laravel:
image: myimage:latest
extra_hosts:
- host.docker.internal:host-gateway
environment:
CHOKIDAR_USEPOLLING: 'true'
WWWUSER: '1000'
XDEBUG_CONFIG: client_host=host.docker.internal
XDEBUG_MODE: 'off'
ports:
- 5173:5173
- 9000:9000
networks:
- net
- public
logging:
driver: json-file
mongo:
image: mongo:latest
command:
- --quiet
- --logpath
- /dev/null
environment:
ME_CONFIG_MONGODB_ADMINPASSWORD: ...
ME_CONFIG_MONGODB_ADMINUSERNAME: ...
MONGO_INITDB_DATABASE: ...
MONGO_INITDB_ROOT_PASSWORD: ...
MONGO_INITDB_ROOT_USERNAME: ...
ports:
- 27017:27017
volumes:
- mongo:/data/db
networks:
- net
logging:
driver: json-file
mysql:
image: mysql:8
environment:
MYSQL_DATABASE: ...
MYSQL_PASSWORD: ...
MYSQL_ROOT_PASSWORD: ...
MYSQL_USER: ...
ports:
- 3306:3306
volumes:
- mysql:/var/lib/mysql
networks:
- net
logging:
driver: json-file
networks:
net:
driver: overlay
public:
external: true
volumes:
mongo:
driver: local
mysql:
driver: local
NGINX docker-compose.yml
version: '3.3'
services:
webserver:
image: mycustomnginximage:latest
ports:
- 80:80
- 8080:8080
- 443:443
networks:
- global
- public
logging:
driver: json-file
networks:
global:
driver: overlay
public:
external: true
NGINX server conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name mywebsite.dev *.mywebsite.dev;
server_tokens off;
root /home/forge/domain.com/public;
# SSL configuration
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/nginx/certificates/mywebsite.pem;
ssl_certificate_key /etc/nginx/certificates/mywebsite.key;
index index.php;
charset utf-8;
location /index.php {
try_files /not_exists @octane;
}
location / {
try_files $uri $uri/ @octane;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
access_log off;
error_log /var/log/nginx/domain.com-error.log error;
error_page 404 /index.php;
location @octane {
set $suffix "";
if ($uri = /index.php) {
set $suffix ?$query_string;
}
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header Scheme $scheme;
proxy_set_header SERVER_PORT $server_port;
proxy_set_header REMOTE_ADDR $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://my_swarm_service_name:9000;
}
}
The result is that the application is reachable directly through IP:9000
but not through https://mywebsite.dev
As if nginx couldn’t divert traffic to the service.
I’ve tryied with:
proxy_pass http://my_swarm_service_name:9000;
proxy_pass http://localhost:9000;
proxy_pass http://docker.service.internal.ip:9000;
How should i use the proxy_pass
directive? Or there are something else wrong?
2
Answers
The service name is
laravel
so, to access the service vip you could use the following hostnames:None of this is going to work out the box however until you add the most crucial piece: Nginx does not do dns resolution at runtime of docker service names unless you tell it to.
You need to configure the resolver Nginx uses to point to dockers container dns:
As they are in the same docker network, you can use either the name of your service which is inside the
docker-compose
, or using the taken IP by docker (docker default IP is172.17.0.1
).So it could be as follows:
or
Also, you can test it inside the nginx container via ping: