I try docker to connect my services for study purpose.
It's all good when I try it in my localhost.
But when I try it on Docker, It's get error when I try to http redirect from product-service to my auth-service.
What I had try is instead using http redirect, I make a new request to auth-service, and It's worked and connected but it's get error when I try to redirect it in Docker.
This is my Redirect Code
I'm using golang and Gin-gonic Library
url := os.Getenv("AUTH_SERVICE_URL") // http://auth-service:8081
c.Redirect(http.StatusSeeOther, url "/refresh?token=" tokenStr)
c.Abort()
return
And this is My new request Code
url := os.Getenv("AUTH_SERVICE_URL") // http://auth-service:8081
request, err := http.NewRequest(http.MethodGet, url "/refresh?token=" tokenStr, nil)
log.Println("make request to", request.URL)
if err != nil {
panic("Internal Server Error")
}
client := http.Client{
Timeout: 30 * time.Second,
}
response, err := client.Do(request)
if err != nil {
panic(fmt.Sprint("unable to get auth request", err.Error()))
}
log.Println("REFRESH TOKEN", response.Header)
I just wondering, why when I use http redirect It's got an error on docker but it works when i try it on my localhost.
I'm using postman for testing and I got this error.
Error: getaddrinfo ENOTFOUND auth-service
But it works when i'm using New Http Request code in my Docker with the same URL.
This is my product-service docker-compose
version: '3'
services:
product-service:
build:
context: .
dockerfile: .
ports:
- "8082:8082"
environment:
AUTH_SERVICE_URL: http://auth-service:8081
DB_DRIVER: postgres
DB_USER: postgres
DB_PASSWORD: password
DB_HOST: postgresDB
DB_PORT: 5431
DB_NAME: v_product
DB_SSL_MODE: disable
PORT: 8082
networks:
- auth-service_default
- product-service_default
depends_on:
- postgresDB
postgresDB:
image: 'postgres:12.12'
ports:
- "5431:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: v_product
networks:
- product-service_default
volumes:
- psql_user:/var/lib/postgresql/data
volumes:
psql_user:
networks:
auth-service_default:
external: true
product-service_default:
external: true
This is my auth-service docker-compose
version: '3'
services:
auth-service:
build:
context: .
dockerfile: .
ports:
- "8081:8081"
environment:
USER_SERVICE_URL: http://user-service:8080
PORT: 8081
networks:
- user-service_default
- auth-service_default
networks:
user-service_default:
external: true
auth-service_default:
external: true
Note: The Endpoint I try to redirect is : GET
:8081/refresh?token=JWTOKEN
and I use See Other
Code for redirect, because It's redirect from POST
request.
CodePudding user response:
An HTTP Redirect works something like this (see the link for a better description with diagrams etc):
- The client (e.g. postman) makes a request (e.g.
GET http://auth-service:8080
) - The server responds with a redirect status (
303
"See Other" in this case) and the new URL (e.g.http://auth-service:8081/refresh?token=blah
) - The client requests the new URL.
So, as per the comments, your app was redirecting to http://auth-service:8081/refresh?token=blah
. The issue is that when the client, which is not a container, tries to lookup the IP address for the host auth-service
it will not find it (it's not in the local hosts
file and whatever DNS server you are using does not know the address). As such the fix is to return a URL that the client can access (e.g. http://127.0.0.1:8081
).
It's worth nothing that even if the client could resolve auth-service
its likely the address would be something like 172.21.0.2
. This is a private address that is not accessible from the host (because you are using a bridge network). This type of network allows containers to communicate amongst themselves (within limits) and to initiate outgoing connections but provides no inbound access for the host or devices attached to the host.
External access is (generally) via published ports; that is the ports: - "5431:5432"
lines in the docker-compose.yml
. These entries allow you to expose a containers port on the host (in this case port 5432
on the container is exposed as port 5432
on the host, but the port numbers can differ).
- How does the network in containers works
Sorry - that's too much to explain in a stack overflow answer! The docker docs are pretty good.
1.5 does it take effect to my redirect action or I'm just wrong specify the host because redirect is actioned by client?
The redirect is performed using the http protocol. HTTP is an application layer protocol; communication usually takes place over TCP/IP connections. It's worth spending a little bit of time to understand all of the different layers involved (there is always more to learn in IT!).
Within the underlying TCP stack the host (and other external systems) can only access the container via the published port. It's worth nothing that DNS (how the host name is mapped to an IP) and IP routing (can traffic from the host reach the container) are separate considerations.
- Is it right the client in this case is Postman ?
Postman is fine. The alternative is to use a browser which will operate in much the same way.
- Am I right if I said when containers trying to connect with named host service, the communication can be done if each containers connect to the same network and it's same like server to server communication?
Containers on the same network can communicate and Docker provides an embedded DNS server that enables them to perform lookups (so map auth-service
to the containers IP address and host.docker.internal
to the host). Its important to note that this embedded DNS server is not used by the host (and would be of limited use anyway because the host cannot communicate directly with the containers via their IP address).
Hopefully that helps - this can get quite confusing, particularly if you don't have much experience with networks. I would note that I often use Edge Routers/reverse proxies in this kind of situation (e.g. Traefik). With this you can just map one port (or perhaps two if you want HTTPS) and Traefik routes the requests to the appropriate container (this may just confuse you now but could be useful in the future!).