muguet

DNS Server & Reverse Proxy for Docker containers

Usage no npm install needed!

<script type="module">
  import muguet from 'https://cdn.skypack.dev/muguet';
</script>

README

Muguet

Muguet

Build Status Coverage Status

Muguet is a DNS Server & Reverse proxy for Docker environments. Compatible with docker-compose, boot2docker and docker-machine

Introduction

When using Docker, it's sometimes a pain to access your containers using specific IPs/ports.

Muguet provides you with a DNS Server that resolves auto-generated hostnames to your containers IPs, plus a Reverse Proxy to access all your web apps on port 80.

Muguet

Prerequisites

Install

  • Install Muguet
npm install -g muguet
  • Start Muguet (as root)
sudo muguet up 

Usage

sudo muguet up [options]

# or
sudo -E bash -c 'muguet up [options]'

Notes:

  • Muguet must be run as root to be able to bind port 80
  • Muguet needs to read DOCKER_HOST and DOCKER_CERT_PATH environment variables. If these variables are not available, Muguet will try to guess it from docker-machine or boot2docker (if detected).
  • If the previous method fails, please consider running Muguet like sudo -E bash -c 'muguet up' as it makes all needed environment variables (eg. from your normal user env) available to the muguet command (eg. to the root user).

Generated hostnames

For each container, Muguet generates several DNS entries:

  • container_id.docker
  • hostname.docker (when running a container with -h option)
  • compose-service.docker (if using Docker Compose)
  • And possibly others based on the org.muguet.dns.subdomain-map label (see below)

Labels

Docker labels are used as configuration settings.

org.muguet.reverse-proxy.enabled

Set it to 1 to enable the reverse-proxy (only enable reverse-proxy for web apps).

org.muguet.reverse-proxy.only-ports

A comma-separated list of ports that you want to proxify.

org.muguet.dns.subdomain-map

A comma-separated list of subdomain:port to map.

Example

# site1 will be accessible on http://site1.docker 
site1:
  build: ./build/docker/site1
  ports:
    - "8081"
  labels:
    # We enable the reverse-proxy so the app will be available on port 80 rather than 8081
    - "org.muguet.reverse-proxy.enabled=1" 
    
# site2 will be accessible on http://site2.docker and on http://back-office.docker 
site2:
  build: ./build/docker/site2
  hostname: back-office
  ports:
    - "8082"
  labels:
    # We enable the reverse-proxy so the app will be available on port 80 rather than 8082
    - "org.muguet.reverse-proxy.enabled=1"
      
# More complex      
# despite not recommended, this container expose several services (mysql, apache, node.js)
# So we have to setup a subdomain-map so each service will be given a distinct hostname
bigcontainer: 
  image: big/big-container
  ports:
    - "3306"
    - "80"
    - "8990"
  labels:
    # Enable reverse-proxy
    - "org.muguet.reverse-proxy.enabled=1"
    # Reverse-proxy only web apps, but NOT MySQL
    - "org.muguet.reverse-proxy.only-ports=80,8990"
    # Will bind:
    #   apache.bigcontainer.docker
    #   nodejs.bigcontainer.docker
    #   mysql.bigcontainer.docker
    - "org.muguet.dns.subdomain-map=apache:80,nodejs:8990,mysql:3306"
    

Dashboard & REST API

A dashboard and a REST API are available on port 9876 (customizable with --api-port) and proxified on port 80. A default domain muguet.docker (or muguet.{domain}) is generated so you can access it through http://muguet.docker

Muguet Dashboard

Muguet dashboard screenshot

Routes

GET /proxy-routes

Sample response:

[
   {
      "hostname": "amc.docker",
      "hostname_aliases": [
         "6e99d3b06a96.docker"
      ],
      "port": 80,
      "container_public_addr": "192.168.59.103",
      "container_public_port": 32807,
      "container_private_addr": "172.17.0.27",
      "container_private_port": 8081,
      "stats": {
         "requestsPerSecond": {
            "mean": 0.2966363784797275,
            "count": 31,
            "currentRate": 0,
            "1MinuteRate": 0.10176713940255401,
            "5MinuteRate": 0.07466202401314313,
            "15MinuteRate": 0.030908019247845135
         }
      }
   },
   {
      "hostname": "bidder.docker",
      "hostname_aliases": [
         "716aed81e348.docker"
      ],
      "port": 80,
      "container_public_addr": "192.168.59.103",
      "container_public_port": 32805,
      "container_private_addr": "172.17.0.26",
      "container_private_port": 8888,
      "stats": {
         "requestsPerSecond": {
            "mean": 0.1465148084182472,
            "count": 11,
            "currentRate": 0.14651508145817516,
            "1MinuteRate": 0.07930845785007225,
            "5MinuteRate": 0.030976204019790073,
            "15MinuteRate": 0.011553349126873487
         }
      }
   },
   {
      "hostname": "ggs.docker",
      "hostname_aliases": [
         "af9fcb68cba5.docker"
      ],
      "port": 80,
      "container_public_addr": "192.168.59.103",
      "container_public_port": 8977,
      "container_private_addr": "172.17.0.24",
      "container_private_port": 80,
      "stats": {
         "requestsPerSecond": {
            "mean": 2.483748695174352,
            "count": 98,
            "currentRate": 2.4837488374391983,
            "1MinuteRate": 1.145862706419387,
            "5MinuteRate": 0.30380239525696306,
            "15MinuteRate": 0.10627732962540533
         }
      }
   },
   {
      "hostname": "elastic.elk.docker",
      "hostname_aliases": [
         "elastic.204e82433b37.docker"
      ],
      "port": 80,
      "container_public_addr": "192.168.59.103",
      "container_public_port": 32799,
      "container_private_addr": "172.17.0.23",
      "container_private_port": 9200,
      "stats": {
         "requestsPerSecond": {
            "mean": 0.17819638140552524,
            "count": 3,
            "currentRate": 0.17819639593817688,
            "1MinuteRate": 0.04060856509152555,
            "5MinuteRate": 0.009592005588775196,
            "15MinuteRate": 0.0032873612833828627
         }
      }
   },
   {
      "hostname": "kibana.elk.docker",
      "hostname_aliases": [
         "kibana.204e82433b37.docker"
      ],
      "port": 80,
      "container_public_addr": "192.168.59.103",
      "container_public_port": 8976,
      "container_private_addr": "172.17.0.23",
      "container_private_port": 80,
      "stats": {
         "requestsPerSecond": {
            "mean": 3.3543803658698623,
            "count": 19,
            "currentRate": 3.354381223966475,
            "1MinuteRate": 0.3038312244085719,
            "5MinuteRate": 0.06280847547785395,
            "15MinuteRate": 0.021052577581392007
         }
      }
   }
]

GET /dns-entries

Sample response:

{
  "amc.docker": "127.0.0.1",
  "6e99d3b06a96.docker": "127.0.0.1",
  "bidder.docker": "127.0.0.1",
  "716aed81e348.docker": "127.0.0.1",
  "aerospike.docker": "172.17.0.25",
  "7bca6d1858ca.docker": "172.17.0.25",
  "ggs.docker": "127.0.0.1",
  "af9fcb68cba5.docker": "127.0.0.1",
  "elk.docker": "127.0.0.1",
  "204e82433b37.docker": "127.0.0.1",
  "elastic.elk.docker": "127.0.0.1",
  "elastic.204e82433b37.docker": "127.0.0.1",
  "kibana.elk.docker": "127.0.0.1",
  "kibana.204e82433b37.docker": "127.0.0.1"
}