dockerproxy

package module
v0.0.0-...-7e15b7d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2016 License: Apache-2.0 Imports: 21 Imported by: 0

README

docker-proxy GoDoc Build Status Go Report Card

The Docker Proxy project consists of a few components. The end goal is to create a system for reverse proxying containers automatically as they are created and destroyed, allowing the end user to map a single endpoint to multiple containers. The project was created with Docker 1.10+ in mind, meaning it supports overlay networks as a first class citizen. The first iteration currently does this using nginx, but a haproxy backend may also be in the works in the future.

The concept, as well as the environment variables used in some of the configuration, was taken from jwilder/nginx-proxy. Unfortunately, I found that I wanted a few things that it did not provide:

  • More introspection into the current websites and containers that are mapped
  • Production stability
  • The ability to watch multiple Docker engines for change, which is very useful in a Swarm environment where the manager does not always report events.

The project is currently a work in progress, but PRs are always welcome, as well as Issues/Feature Requests.

Building

The project can be built and fetched with a go get github.com/nickvanw/docker-proxy and go build from cmd/nginxproxy

There is also a Dockerfile located in cmd/nginxproxy that will build an alpine container using the built binary in cmd/nginxproxy. There are some caveats to this:

  • The Dockerfile is built using alpine, meaning there is no glibc - I recommend statically compiling with musl
  • The Dockerfile uses the latest version of nginx in the alpine stable repository, which will sometimes lag behind the latest build

Configuring

Configuration of the nginx proxy is done via flags and/or environment variables. The latest list of them, as well as a description of what they do, can be found by building the binary and running nginxproxy -h. A few of the more important variables:

  • DOCKER_HOST should point to the unix or TCP endpoint where the proxy can pull the list of containers, as well as events from.
  • NGINX_CONF is the file that the nginx proxy will write to
  • NGINX_RELOAD is the command the nginx proxy will run to reload nginx when the containers are updated

The rest of the flags are useful for enabling additional functions, such as shipping nginx and proxy logs to syslog, or enabling sentry reporting for errors.

Deploying

The strategies used to deploy this will change depending on how your Docker setup works. Currently, I'm running it with a 5 node swarm cluster with three of the nodes running this service, using round-robin DNS to split the load across them.

Each host has the Docker container deployed out with ports 80 and 443 bonded to their external addresses. They are all listening to events on the swarm master, as well as all of the swarm nodes. This causes a small amount of additional load, but the debounce usually results in the container list only being pulled once, and there is a significantly lower change of events getting dropped.

Usage

Using the service is designed to be as simple as possible - there is only one environment variable necessary on new containers for the proxy to begin working, VIRTUAL_HOST. If the container exposes more than one port, VIRTUAL_PORT is required as well, or the service will be unaware of where to proxy to, and will ignore the container.

Example:

docker run -e VIRTUAL_HOST=something.nvw.io ...

If the DNS of something.nvw.io is pointed to the container(s) running the proxy, and the image exposes a single port, traffic will be forwarded seamlessly.

HTTPS

HTTPS is fully supported - a container with VIRTUAL_HOST=foo.bar.com should have a foo.bar.com.crt and foo.bar.com.key file in the certs directory (configured in the service). It will automatically redirect non-https access to the https location, and will set an HSTS header.

Arbitrary configuration options

Currently, there are a few environment variables that will map to nginx configuration directives. More are very easy to add, I just haven't had a use:

  • NGINX_CLIENT_MAX_BODY_SIZE will set the max body size for the virtual host
  • AUTH_USER and AUTH_PASS (with a configured htpasswd directory) will create an htpasswd file and use that for basic auth. AUTH_PASS will be printed verbatim into the file, so use the encryption scheme of choice, but I recommend bcrypt.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrInvalidLine is returned when a malformed environment line is passed
	ErrInvalidLine = errors.New("invalid line passed to parse")
)
View Source
var (
	// ErrInvalidURL is returned when the URL is invalid for a Docker endpoint
	ErrInvalidURL = errors.New("unknown URL scheme for docker endpoint")
)

Functions

This section is empty.

Types

type AdminSocket

type AdminSocket struct {
	sync.Mutex
	// contains filtered or unexported fields
}

AdminSocket exposes an admin socket for loooking at information about the service, as well as what sites are mapped

func (*AdminSocket) Name

func (a *AdminSocket) Name() string

Name identifies the admin socket

func (*AdminSocket) NewSocket

func (a *AdminSocket) NewSocket() *AdminSocket

NewSocket returns a new admin socket for starting

func (*AdminSocket) Start

func (a *AdminSocket) Start(asok string) error

Start listens at the specified file for HTTP requests. It is blocking, so it should be run in a goroutine

func (*AdminSocket) Update

func (a *AdminSocket) Update(sites []Site) error

Update is used to set the current list of sites the admin socket returns to be registered with the Manager for automatic updating

type DockerConfig

type DockerConfig struct {
	Watchers []string
	Leader   string
	TLS      bool
	Cert     string
	CA       string
	Key      string
}

DockerConfig contains the hosts/sockets of the Docker API to pull a list of containers from, as well as any other watchers to trigger events from

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager handles the state and coordinates updates of the mappings of Containers -> Sites

func New

func New(cfg DockerConfig) (*Manager, error)

New creates a new manager with the specified Docker configuration. it will Ping the Leader to make sure the configuration is valid.

func (*Manager) HandleSignals

func (m *Manager) HandleSignals(sigs ...os.Signal)

HandleSignals listenes for the specified signals and reloads when they are signaled

func (*Manager) Register

func (m *Manager) Register(w watcher)

Register adds a watcher to be updated when the containers change

func (*Manager) Start

func (m *Manager) Start(ctx context.Context, d time.Duration)

Start begins waiting for events on the Docker endpoint, as well as polling every `d` seconds

type Mapping

type Mapping struct {
	Address string
	Port    int64
	Network string
}

Mapping represents an IP/Port as well as optional network name to map the current container to the container we're representing

type Site

type Site struct {
	ID      string
	Names   []string
	Contact Mapping
	Hosts   []string
	Env     map[string]string
}

Site represents a single containers' site, which consists of the container the site is running in, the IP/Port necessary to contact it, as well as 1+ virtual host to advertise.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL