Home > database >  Does Docker Support Redirect HTTP?
Does Docker Support Redirect HTTP?

Time:08-17

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):

  1. The client (e.g. postman) makes a request (e.g. GET http://auth-service:8080)
  2. 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)
  3. 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).

  1. 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.

  1. 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.

  1. 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!).

  • Related