I am implementing reverse proxy using caddy in docker container. i have docker-compose file in which i specifed three service caddy, nginx, httpd. i also configured caddyfile in which i redirected my request to servers. when i run '$docker-compose up' all the containers working perfectlly fine. but when i go to
http://localhost/ - show blank white page
http://localhost:8080/ - this site cant be reach
http://localhost:8081/ - this site cant be reach
nginx_container_IP - show nginx page
httpd_container_IP - show httpd page
docker-compose.yaml
version: '3'
services:
proxy:
image: caddy:2.3.0-alpine
ports:
- "80:80"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
service1:
image: nginx:latest
expose:
- "8080"
service2:
image: httpd:latest
expose:
- "8081"
Caddyfile
hostname:80 {
reverse_proxy service1:8080
reverse_proxy service2:8081
}
Caddy container logs
{"level":"info","ts":1675247772.029432,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"info","ts":1675247772.033348,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["localhost:2019","[::1]:2019","127.0.0.1:2019"]}
{"level":"info","ts":1675247772.033649,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server","server_name":"srv0","http_port":80}
{"level":"info","ts":1675247772.0337453,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc0002f52d0"}
{"level":"info","ts":1675247772.0342908,"logger":"tls","msg":"cleaned up storage units"}
{"level":"info","ts":1675247772.034485,"msg":"autosaved config","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1675247772.0345104,"msg":"serving initial configuration"}
I want that when i request to localhost my request should be forwarded to nginx and httpd backend servers.
Related
So I'm currently building a docker setup with a REST API and a separate frontend. My backend consists of Symfony 5.2.6 as REST API and my frontend is a simple Vue application.
When I try to call my API from the vue application via localhost or 127.0.0.1, I get a "Connection refused" error. When I try to call the API via the external IP of my server, I run into CORS issues. This is my first setup like this, so I'm kind of at a loss.
This is my docker setup:
version: "3.8"
services:
# VUE-JS Instance
client:
build: client
restart: always
logging:
driver: none
volumes:
- ./client:/app
- /app/node_modules
environment:
- CHOKIDAR_USEPOLLING=true
- NODE_ENV=development
ports:
- 8080:8080
# SERVER
php:
build: php-fpm
restart: always
ports:
- "9002:9000"
volumes:
- ./server:/var/www/:cached
- ./logs/symfony:/var/www/var/logs:cached
# WEBSERVER
nginx:
build: nginx
restart: always
ports:
- "80:80"
volumes_from:
- php
volumes:
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
- ./logs/nginx/:/var/log/nginx:cached
So what is the correct way to establish the connection between those two containers?
The client app runs on port 8080 but nginx on 80 is a different URL and it should be a CORS error.
To avoid it, in the PHP app, you have to add response header:
Access-Control-Allow-Origin: http://localhost:8080 or
Access-Control-Allow-Origin: *.
Another solution is to configure all in one domain on this same port.
I am trying to setup an nginx container that will show at the "http://server_ip/" path the nginx html page and on the "/app" path the tutum/hello-world container. as a follow up, want to be able to get to the "hello-world" container only from the "http://server_ip/app" path and not via http://server_ip:1500.
I created the following docker-compose:
version: '3'
services:
proxy:
container_name: proxy
image: nginx
ports:
- "80:80"
volumes:
- $PWD/html:/usr/share/nginx/html
- $PWD/config/nginx.conf:/etc/nginx/conf.d/nginx.conf
networks:
- backend
webapp:
container_name: webapp
image: tutum/hello-world
ports:
- "1500:80"
networks:
- backend
networks:
backend:
then I have the following nginx.conf file:
server {
listen 80; # not really needed, but more informative
location = / {
root /usr/share/nginx/html;
}
location = /app/ {
proxy_pass http://localhost:1500/;
}
}
If I try to get to each of the containers by their http://server_ip:PORT, I get there. if I try http://server_ip/app I get "404 not found". what am I missing? did I put the conf file in the wrong folder? how do I limit the availability of the "hello-world" only to the "http://server_ip/app" path and not via "http://server_ip:1500".
Your containers using the "backend" docker network, as you stated in the compose file.
Inside that they reach each other with the service names, so from the "proxy" service you can reach "webapp" service on http://webapp (or http://webapp:80) and from the "webapp" service you can reach "proxy" on http://proxy or (http://proxy:80).
On your computer if you type http://localhost:1500/ you will reach the webapp service and if you type http://localhost:80/ you will reach proxy service.
The port mapping 1500:80 means that your computer 1500 port is mapped to the webapp container 80 port.
So in nginx.conf do this:
proxy_pass http://webapp:80/;
Also if you want to make your webapp not accessible from your host on localhost:1500 remove the ports part in the webapp service spec:
version: '3'
services:
proxy:
container_name: proxy
image: nginx:1.11
ports:
- "80:80"
volumes:
- $PWD/html:/usr/share/nginx/html
- $PWD/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- backend
webapp:
container_name: webapp
image: tutum/hello-world
networks:
- backend
networks:
backend:
I am trying to set up a sample application with the Traefik reverse proxy in Docker.
I am using Traefik v2.2 for this project which has significant differences from Traefik.v1.0.
Here is my docker-compose.yml file:
version: '3'
services:
traefik:
# The official v2 Traefik docker image
image: traefik:v2.2
# Enables the web UI and tells Traefik to listen to docker
command:
- --api.insecure=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --entrypoints.web.address=:80
ports:
# The HTTP port
- "89:80"
# The Web UI (enabled by --api.insecure=true)
- "8089:8080"
volumes:
# So that Traefik can listen to the Docker events
- "/var/run/docker.sock:/var/run/docker.sock:ro"
whoami:
# A container that exposes an API to show its IP address
image: containous/whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
- "traefik.http.routers.whoami.entrypoints=web"
I can access Traefik's dashboard when I go to localhost:8089 on my web browser, but I cannot access the whoami application when I type in the whoami.localhost address on my web browser. I'm just wondering if there is anything I need to change before I can access it, or do I need to change the host from whoami.localhost to localhost:3000 since that's the port I want to access the application in.
One problem I am spotting is that you exposed container port 80 of the traefik container to the host port 89. If you type in whoami.localhost in your web browser, your browser is going to search for an application on host port 80 at that address (since localhost maps natively to port 80), but it is not going to find anything there, because it can only be found at port 89. From my understanding, you should be able to access the application via the command line with the command curl -H Host:whoami.localhost http://127.0.0.1:89. Unfortunately, I am unsure how the URL whoami.localhost:89 is handled by your browser respectively by your DNS.
You can to modify the docker-compose.yml file this way:
version: "3"
services:
traefik:
# The official v2 Traefik docker image
image: traefik:v2.2
# Enables the web UI and tells Traefik to listen to docker
command:
- --api.insecure=true
- --providers.docker=true
ports:
# The HTTP port
- "89:80"
# The Web UI (enabled by --api.insecure=true)
- "8089:8080"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
whoami:
# A container that exposes an API to show its IP address
image: containous/whoami
labels:
- traefik.http.routers.whoami.rule=Host(`whoami.localhost`)
And then you can access the application on your command terminal by typing in:
curl -H Host:whoami.localhost http://127.0.0.1:89
Note: whoami.localhost can be whoami.docker.localhost or app.localhost or whatever you want. The thing here is that you should localhost attached to the end, except if you're adding a Fully Qualifies Domain name (FQDN).
That's all.
I hope this helps
I want to use nginx reverse proxy as an APIGateway in my microservice architecture
Problem: Nginx is unable to proxy_pass to my payment_service running in a different container. However, when I try to curl payment_service:3000 from inside nginx container, it works. So the network is ok.
docker-compose.yml
version: '3'
services:
payment_service:
container_name: payment_service
build: ./payment
ports:
- "3000:3000"
volumes:
- ./payment:/usr/app
networks:
- microservice-network
api_gateway:
image: nginx:latest
container_name: api_gateway
restart: always
volumes:
- ./default.conf:/etc/nginx/conf.d/default.conf
ports:
- 8080:8080
- 443:443
depends_on:
- payment_service
networks:
- microservice-network
networks:
microservice-network:
driver: bridge
default.conf
upstream payment_server {
server payment_service:3000 max_fails=10;
}
server {
listen 8080;
location /api/v1/payment {
proxy_pass http://payment_server;
}
}
Payment service is working fine when I directly access it using http://localhost:3000
But dont work with http://localhost:8080/api/v1/payment
According to the docs
If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI...
I don't know what your payment service is expecting, but I'm assuming you're trying to hit the root path. You need to add a trailing slash to the proxy_pass:
location /api/v1/payment {
proxy_pass http://payment_server/;
}
otherwise the request will be made as
http://payment_service:3000/api/v1/payment
I am trying to run a very simple Docker-compose.yml file based on varnish and php7.1+apache2 services:
version: "3"
services:
cache:
image: varnish
container_name: varnish
volumes:
- ./default.vcl:/etc/varnish/default.vcl
links:
- web:webserver
depends_on:
- web
ports:
- 80:80
web:
image: benit/stretch-php-7.1
container_name: web
ports:
- 8080:80
volumes:
- ./index.php:/var/www/html/index.php
The default.vcl contains:
vcl 4.0;
backend default {
.host = "webserver";
.port = "8080";
}
I encountered the following error when browsing at http://localhost/:
Error 503 Backend fetch failed
Backend fetch failed
Guru Meditation:
XID: 9
Varnish cache server
The web service works fine when I test it at http://localhost:8080/.
What's wrong?
You need to configure varnish to communicate with "web" on port "80" rather than "webserver" on port "8080".
The "web" comes from the service name in your compose file. There's no need to set a container name, and indeed that breaks the ability to scale or perform rolling updates if you transition to swarm mode. Links have been deprecated in favor of shared networks that docker compose will provide (links are very brittle, breaking if you update the web container). And depends_on does not assure that the other service is ready to receive requests. If you have a hard dependency to hold varnish from starting until the web server is ready to receive requests, then you'll want to update the entrypoint with a task to wait for the remote port to be reachable and have a plan for how to handle the web server going down.
The port 80 comes from the container port. There is no need to publish port 8080 on the docker host if you only want to access it through varnish, and this would be a security risk to many. Containers communicate directly to the container port, not back out to the host and mapped back into a container.
The resulting compose file could look like:
version: "3"
services:
cache:
image: varnish
container_name: varnish
volumes:
- ./default.vcl:/etc/varnish/default.vcl
ports:
- 80:80
web:
image: benit/stretch-php-7.1
volumes:
- ./index.php:/var/www/html/index.php
And importantly, your varnish config would look like:
vcl 4.0;
backend default {
.host = "web";
.port = "80";
}