Friendly url between containers/Docker images

Asked

Viewed 321 times

5

I have some projects already ready that will use Docker, but they will be in separate images.

The question is as follows: It is possible for other images to be accessed through a "friendly url".

Example:

  • Main container is in www.teste.com
  • And the other being accessed like this: www.teste.com/projeto2, www.teste.com/projeto3, and would be other containers.

2 answers

1

Docker only forwards ports. A url-based distribution is a capability served by webservers and load balancers.

Nginx, or Haproxy are excellent options for making this type of distribution. Both are very well known, using them is a still unnamed Pattern, but it is possible to see them present in several diagrams that present multiple containers.

Both have extensive documentation available for research, but Nginx is simpler.

If using swarm, then any worker in your park can redirect traffic to the appropriate container, this is done transparently, however it is ideal to put a loadbalancer to manage it.

1

You can solve your problem through several approaches. The one I would use would be as follows.

A single container would be responsible for responding to requests through the URL www.teste.com, as if it were a load Balancer. This container would receive the path requests and, depending on the path, would make another request for a second container. This strategy is up to you.

For my Alancer load, I wrote a code in Go that receives the request and the transfer to another server based on the path called:

package main

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func router(w http.ResponseWriter, r *http.Request) {

    var url string

    switch r.URL.Path {
    case "/stack":
        url = "http://app1.dev" + r.URL.Path
    case "/overflow":
        url = "http://app2.dev" + r.URL.Path
    default:
        url = "http://app3.dev" + r.URL.Path
    }

    resp, err := http.Get(url)
    if err != nil {
        w.WriteHeader(500)
        w.Write([]byte(fmt.Sprintf("Could not call '%s'.\n", url)))
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        w.WriteHeader(500)
        w.Write([]byte(fmt.Sprintf("Could not read '%s'.\n", url)))
    }

    w.WriteHeader(resp.StatusCode)
    w.Write(body)
}

func main() {
    http.HandleFunc("/", router)
    err := http.ListenAndServe(":80", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

To orchestrate the containers, I chose to write a docker-compose.yml, in which I discriminate all application containers:

mm_lb:
  image: mm/lb:latest
  container_name: mm_lb
  links:
    - mm_app1:app1.dev
    - mm_app2:app2.dev
    - mm_app3:app3.dev
  ports:
    - "80"

mm_app1:
  image: mm/app1:latest
  container_name: mm_app1
  ports:
    - "80"

mm_app2:
  image: mm/app2:latest
  container_name: mm_app2
  ports:
    - "80"

mm_app3:
  image: mm/app3:latest
  container_name: mm_app3
  ports:
    - "80"

Note that the container configuration mm_lb creates links with other containers. That’s how I can call them from the load Alancer which in turn responds to the main URL.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.