Coder Social home page Coder Social logo

docker-gen's Introduction

docker-gen

Tests GitHub release Docker Image Size Docker stars Docker pulls

docker-gen is a file generator that renders templates using docker container meta-data.

It can be used to generate various kinds of files for:

  • Centralized logging - fluentd, logstash or other centralized logging tools that tail the containers JSON log file or files within the container.
  • Log Rotation - logrotate files to rotate container JSON log files
  • Reverse Proxy Configs - nginx, haproxy, etc. reverse proxy configs to route requests from the host to containers
  • Service Discovery - Scripts (python, bash, etc..) to register containers within etcd, hipache, etc..

Installation

There are three common ways to run docker-gen:

  • on the host
  • bundled in a container with another application
  • separate standalone containers

Host Install

Download the version you need, untar, and install to your PATH.

wget https://github.com/nginx-proxy/docker-gen/releases/download/0.12.0/docker-gen-linux-amd64-0.12.0.tar.gz
tar xvzf docker-gen-linux-amd64-0.12.0.tar.gz
./docker-gen

Bundled Container Install

Docker-gen can be bundled inside of a container along-side applications.

nginx-proxy/nginx-proxy trusted build is an example of running docker-gen within a container along-side nginx. jwilder/docker-register is an example of running docker-gen within a container to do service registration with etcd.

Separate Container Install

It can also be run as two separate containers using the nginx-proxy/docker-gen image, together with virtually any other image.

This is how you could run the official nginx image and have docker-gen generate a reverse proxy config in the same way that nginx-proxy works. You may want to do this to prevent having the docker socket bound to a publicly exposed container service.

Start nginx with a shared volume:

docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx

Fetch the template and start the docker-gen container with the shared volume:

mkdir -p /tmp/templates && cd /tmp/templates
curl -o nginx.tmpl https://raw.githubusercontent.com/nginx-proxy/docker-gen/main/templates/nginx.tmpl
docker run -d --name nginx-gen --volumes-from nginx \
   -v /var/run/docker.sock:/tmp/docker.sock:rw \
   -v /tmp/templates:/etc/docker-gen/templates \
   -t nginxproxy/docker-gen -notify-sighup nginx -watch -only-exposed /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf

Start a container, taking note of any Environment variables a container expects. See the top of a template for details.

docker run --env VIRTUAL_HOST='example.com' --env VIRTUAL_PORT=80 ...

Usage

$ docker-gen
Usage: docker-gen [options] template [dest]

Generate files from docker container meta-data

Options:
  -config value
      config files with template directives. Config files will be merged if this option is specified multiple times. (default [])
  -endpoint string
      docker api endpoint (tcp|unix://..). Default unix:///var/run/docker.sock
  -interval int
      notify command interval (secs)
  -keep-blank-lines
      keep blank lines in the output file
  -notify restart xyz
      run command after template is regenerated (e.g restart xyz)
  -notify-output
      log the output(stdout/stderr) of notify command
  -notify-sighup container-ID
      send HUP signal to container.
      Equivalent to 'docker kill -s HUP container-ID', or `-notify-container container-ID -notify-signal 1`.
      You can pass this option multiple times to send HUP to multiple containers.
  -notify-container container-ID
      send -notify-signal signal (defaults to 1 / HUP) to container.
      You can pass this option multiple times to notify multiple containers.
  -notify-filter key=value
      container filter for notification (e.g -notify-filter name=foo).
      You can pass this option multiple times to combine filters with AND.
      https://docs.docker.com/engine/reference/commandline/ps/#filter
  -notify-signal signal
      signal to send to the -notify-container and -notify-filter. -1 to call docker restart. Defaults to 1 aka. HUP.
      All available signals available on the dockerclient
      https://github.com/fsouza/go-dockerclient/blob/main/signal.go
  -only-exposed
      only include containers with exposed ports
  -only-published
      only include containers with published ports (implies -only-exposed)
  -include-stopped
      include stopped containers
  -tlscacert string
      path to TLS CA certificate file (default "~/.docker/machine/machines/default/ca.pem")
  -tlscert string
      path to TLS client certificate file (default "~/.docker/machine/machines/default/cert.pem")
  -tlskey string
      path to TLS client key file (default "~/.docker/machine/machines/default/key.pem")
  -tlsverify
      verify docker daemon's TLS certicate (default true)
  -version
      show version
  -watch
      watch for container changes
  -wait
      minimum (and/or maximum) duration to wait after each container change before triggering

Arguments:
  template - path to a template to generate
  dest - path to write the template. If not specfied, STDOUT is used

Environment Variables:
  DOCKER_HOST - default value for -endpoint
  DOCKER_CERT_PATH - directory path containing key.pem, cert.pm and ca.pem
  DOCKER_TLS_VERIFY - enable client TLS verification]

If no <dest> file is specified, the output is sent to stdout. Mainly useful for debugging.

Configuration file

Using the -config flag from above you can tell docker-gen to use the specified config file instead of command-line options. Multiple templates can be defined and they will be executed in the order that they appear in the config file.

An example configuration file, docker-gen.cfg can be found in the examples folder.

Configuration File Syntax

[[config]]
# Starts a configuration section

dest = "path/to/a/file"
# path to write the template. If not specfied, STDOUT is used

notifycmd = "/etc/init.d/foo reload"
# run command after template is regenerated (e.g restart xyz)

onlyexposed = true
# only include containers with exposed ports

template = "/path/to/a/template/file.tmpl"
# path to a template to generate

watch = true
# watch for container changes

wait = "500ms:2s"
# debounce changes with a min:max duration. Only applicable if watch = true


[config.NotifyContainers]
# Starts a notify container section

containername = 1
# container name followed by the signal to send

container_id = 1
# or the container id can be used followed by the signal to send

Putting it all together here is an example configuration file.

[[config]]
template = "/etc/nginx/nginx.conf.tmpl"
dest = "/etc/nginx/sites-available/default"
onlyexposed = true
notifycmd = "/etc/init.d/nginx reload"

[[config]]
template = "/etc/logrotate.conf.tmpl"
dest = "/etc/logrotate.d/docker"
watch = true

[[config]]
template = "/etc/docker-gen/templates/nginx.tmpl"
dest = "/etc/nginx/conf.d/default.conf"
watch = true
wait = "500ms:2s"

[config.NotifyContainers]
nginx = 1  # 1 is a signal number to be sent; here SIGHUP
e75a60548dc9 = 1  # a key can be either container name (nginx) or ID

Templating

The templates used by docker-gen are written using the Go text/template language. In addition to the built-in functions supplied by Go, docker-gen uses sprig and some additional functions to make it simpler (or possible) to generate your desired output. Some templates rely on environment variables within the container to make decisions on what to generate from the template.

Several templates may be parsed at once by using a semicolon (;) to delimit the template value. This can be used as a proxy for Golang's nested template functionality. In all cases, the main rendered template should go first.

[[config]]
template = "/etc/docker-gen/templates/nginx.tmpl;/etc/docker-gen/templates/header.tmpl"
dest = "/etc/nginx/conf.d/default.conf"
watch = true
wait = "500ms:2s"

Emit Structure

Within the templates, the object emitted by docker-gen will be a structure consisting of following Go structs:

type RuntimeContainer struct {
    ID           string
    Created      time.Time
    Addresses    []Address
    Networks     []Network
    Gateway      string
    Name         string
    Hostname     string
    Image        DockerImage
    Env          map[string]string
    Volumes      map[string]Volume
    Node         SwarmNode
    Labels       map[string]string
    IP           string
    IP6LinkLocal string
    IP6Global    string
    Mounts       []Mount
    State        State
}

type Address struct {
    IP           string
    IP6LinkLocal string
    IP6Global    string
    Port         string
    HostPort     string
    Proto        string
    HostIP       string
}

type Network struct {
    IP                  string
    Name                string
    Gateway             string
    EndpointID          string
    IPv6Gateway         string
    GlobalIPv6Address   string
    MacAddress          string
    GlobalIPv6PrefixLen int
    IPPrefixLen         int
    Internal            bool
}

type DockerImage struct {
    Registry   string
    Repository string
    Tag        string
}

type Mount struct {
  Name        string
  Source      string
  Destination string
  Driver      string
  Mode        string
  RW          bool
}

type Volume struct {
    Path      string
    HostPath  string
    ReadWrite bool
}

type SwarmNode struct {
    ID      string
    Name    string
    Address Address
}

type State struct {
	Running bool
	Health  Health
}

type Health struct {
	Status string
}

// Accessible from the root in templates as .Docker
type Docker struct {
    Name                 string
    NumContainers        int
    NumImages            int
    Version              string
    ApiVersion           string
    GoVersion            string
    OperatingSystem      string
    Architecture         string
    CurrentContainerID   string
}

// Host environment variables accessible from root in templates as .Env

For example, this is a JSON version of an emitted RuntimeContainer struct:

{
  "ID": "71e9768075836eb38557adcfc71a207386a0c597dbeda240cf905df79b18cebf",
  "Addresses": [
    {
      "IP": "172.17.0.4",
      "Port": "22",
      "Proto": "tcp",
      "HostIP": "192.168.10.24",
      "HostPort": "2222"
    }
  ],
  "Gateway": "172.17.42.1",
  "Node": {
    "ID": "I2VY:P7PF:TZD5:PGWB:QTI7:QDSP:C5UD:DYKR:XKKK:TRG2:M2BL:DFUN",
    "Name": "docker-test",
    "Address": {
      "IP": "192.168.10.24"
    }
  },
  "Labels": {
    "operatingsystem": "Ubuntu 14.04.2 LTS",
    "storagedriver": "devicemapper",
    "anything_foo": "something_bar"
  },
  "IP": "172.17.0.4",
  "Name": "docker_register",
  "Hostname": "71e976807583",
  "Image": {
    "Registry": "jwilder",
    "Repository": "docker-register"
  },
  "Env": {
    "ETCD_HOST": "172.17.42.1:4001",
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "DOCKER_HOST": "unix:///var/run/docker.sock",
    "HOST_IP": "172.17.42.1"
  },
  "Volumes": {
    "/mnt": {
      "Path": "/mnt",
      "HostPath": "/Users/joebob/tmp",
      "ReadWrite": true
    }
  }
}

Functions

  • Functions from Go
  • Functions from Sprig v3, except for those that have the same name as one of the following functions.
  • closest $array $value: Returns the longest matching substring in $array that matches $value
  • coalesce ...: Returns the first non-nil argument.
  • comment $delimiter $string: Returns $string with each line prefixed by $delimiter (helpful for debugging combined with Sprig toPrettyJson: {{ toPrettyJson $ | comment "#" }}).
  • contains $map $key: Returns true if $map contains $key. Takes maps from string to any type.
  • dir $path: Returns an array of filenames in the specified $path.
  • exists $path: Returns true if $path refers to an existing file or directory. Takes a string.
  • eval $templateName [$data]: Evaluates the named template like Go's built-in template action, but instead of writing out the result it returns the result as a string so that it can be post-processed. The $data argument may be omitted, which is equivalent to passing nil.
  • groupBy $containers $fieldPath: Groups an array of RuntimeContainer instances based on the values of a field path expression $fieldPath. A field path expression is a dot-delimited list of map keys or struct member names specifying the path from container to a nested value, which must be a string. Returns a map from the value of the field path expression to an array of containers having that value. Containers that do not have a value for the field path in question are omitted.
  • groupByWithDefault $containers $fieldPath $defaultValue: Returns the same as groupBy, but containers that do not have a value for the field path are instead included in the map under the $defaultValue key.
  • groupByKeys $containers $fieldPath: Returns the same as groupBy but only returns the keys of the map.
  • groupByMulti $containers $fieldPath $sep: Like groupBy, but the string value specified by $fieldPath is first split by $sep into a list of strings. A container whose $fieldPath value contains a list of strings will show up in the map output under each of those strings.
  • groupByLabel $containers $label: Returns the same as groupBy but grouping by the given label's value. Containers that do not have the $label set are omitted.
  • groupByLabelWithDefault $containers $label $defaultValue: Returns the same as groupBy but grouping by the given label's value. Containers that do not have the $label set are included in the map under the $defaultValue key.
  • include $file: Returns content of $file, and empty string if file reading error.
  • intersect $slice1 $slice2: Returns the strings that exist in both string slices.
  • fromYaml $string / mustFromYaml $string: Similar to Sprig's fromJson / mustFromJson, but for YAML.
  • toYaml $dict / mustToYaml $dict: Similar to Sprig's toJson / mustToJson, but for YAML.
  • keys $map: Returns the keys from $map. If $map is nil, a nil is returned. If $map is not a map, an error will be thrown.
  • sortStringsAsc $strings: Returns a slice of strings $strings sorted in ascending order.
  • sortStringsDesc $strings: Returns a slice of strings $strings sorted in descending (reverse) order.
  • sortObjectsByKeysAsc $objects $fieldPath: Returns the array $objects, sorted in ascending order based on the values of a field path expression $fieldPath.
  • sortObjectsByKeysDesc $objects $fieldPath: Returns the array $objects, sorted in descending (reverse) order based on the values of a field path expression $fieldPath.
  • when $condition $trueValue $falseValue: Returns the $trueValue when the $condition is true and the $falseValue otherwise
  • where $items $fieldPath $value: Filters an array or slice based on the values of a field path expression $fieldPath. A field path expression is a dot-delimited list of map keys or struct member names specifying the path from container to a nested value. Returns an array of items having that value.
  • whereNot $items $fieldPath $value: Filters an array or slice based on the values of a field path expression $fieldPath. A field path expression is a dot-delimited list of map keys or struct member names specifying the path from container to a nested value. Returns an array of items not having that value.
  • whereExist $items $fieldPath: Like where, but returns only items where $fieldPath exists (is not nil).
  • whereNotExist $items $fieldPath: Like where, but returns only items where $fieldPath does not exist (is nil).
  • whereAny $items $fieldPath $sep $values: Like where, but the string value specified by $fieldPath is first split by $sep into a list of strings. The comparison value is a string slice with possible matches. Returns items which OR intersect these values.
  • whereAll $items $fieldPath $sep $values: Like whereAny, except all $values must exist in the $fieldPath.
  • whereLabelExists $containers $label: Filters a slice of containers based on the existence of the label $label.
  • whereLabelDoesNotExist $containers $label: Filters a slice of containers based on the non-existence of the label $label.
  • whereLabelValueMatches $containers $label $pattern: Filters a slice of containers based on the existence of the label $label with values matching the regular expression $pattern.

Sprig functions that have the same name as docker-gen function (but different behaviour) are made available with the sprig prefix:

  • sprigCoalesce ...: Alias for Sprig's coalesce.
  • sprigContains $string $string: Alias for Sprig's contains.
  • sprigDir $path: Alias for Sprig's dir.
  • sprigReplace $old $new $string: Alias for Sprig's replace.
  • sprigSplit $sep $string: Alias for Sprig's split.
  • sprigSplitn $sep $count $string": Alias for Sprig's splitn.

Some functions are aliases for Go's strings package functions:

  • parseBool $string: Alias for strconv.ParseBool. Returns the boolean value represented by $string. It accepts 1, t, T, TRUE, true, True, 0, f, F, FALSE, false, False. Any other value returns an error.
  • replace $string $old $new $count: Alias for strings.Replace. Replaces up to $count occurences of $old with $new in $string.
  • split $string $sep: Alias for strings.Split. Splits $string into a slice of substrings delimited by $sep.
  • splitN $string $sep $count: Alias for strings.SplitN. Splits $string into a slice of substrings delimited by $sep, with number of substrings returned determined by $count.
  • toLower $string: Alias for strings.ToLower. Replace capital letters in $string to lowercase.
  • toUpper $string: Alias for strings.ToUpper. Replace lowercase letters in $string to uppercase.

Those have been aliased to Sprig functions with the same behaviour as the original docker-gen function:


Examples

NGINX Reverse Proxy Config

nginxproxy/nginx-proxy trusted build.

Start nginx-proxy:

docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock -t nginxproxy/nginx-proxy

Then start containers with a VIRTUAL_HOST (and the VIRTUAL_PORT if more than one port is exposed) env variable:

docker run -e VIRTUAL_HOST=foo.bar.com -e VIRTUAL_PORT=80 -t ...

If you wanted to run docker-gen directly on the host, you could do it with:

docker-gen -only-published -watch -notify "/etc/init.d/nginx reload" templates/nginx.tmpl /etc/nginx/sites-enabled/default

Fluentd Log Management

This template generate a fluentd.conf file used by fluentd. It would then ship log files off the host.

docker-gen -watch -notify "restart fluentd" templates/fluentd.tmpl /etc/fluent/fluent.conf

Service Discovery in Etcd

This template is an example of generating a script that is then executed. This template generates a python script that is then executed which register containers in Etcd using its HTTP API.

docker-gen -notify "/bin/bash /tmp/etcd.sh" -interval 10 templates/etcd.tmpl /tmp/etcd.sh

Development

This project uses Go Modules for managing 3rd party dependencies. This means that at least go 1.11 is required.

For go 1.11 and go 1.12 it is additionally required to manually enable support by setting GO111MODULE=on. For later versions, this is not required.

git clone <your fork>
cd <your fork>
make get-deps
make

License

MIT

docker-gen's People

Contributors

alexturek avatar anthonyraymond avatar baptistedonaux avatar bcicen avatar buchdag avatar codekitchen avatar datacoda avatar dependabot[bot] avatar frederickjh avatar haraldnordgren avatar ipanousis avatar justadam avatar jwilder avatar lanwen avatar lukas2511 avatar maubergine avatar md5 avatar minhdoboi avatar mlatorre31 avatar nickbolles avatar nicolasdorier avatar niekoost avatar oliv3r avatar punkstar avatar rhansen avatar tarasov65536 avatar testwill avatar tkw1536 avatar viranch avatar webner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

docker-gen's Issues

debounce events

I have a script that starts up 3 docker containers when I deploy, it would be nice to only trigger a single notify event. Currently it appears to be signaling nginx for every container run

delay on notify

my server takes a little bit of time to start up, so I'd like to have a delay before notifying nginx and adding to the proxy. This sort of ties into #42, as I'd only want a single event if multiple were fired within the delay interval

groupByMulti keys clarification

Say I have an env field setup

           Container A: FOO
           Container B: FOO,BAR

groupByMulti returns the keys ["FOO", "FOO,BAR"] instead of the expected ["FOO", "BAR"] The docs are a bit unclear about this so I'm wondering if this is the intended behavior.

truncated responses

I actually reported this in your nginx-proxy repo - but I'm 99% sure it really belongs here.

As it stands, nginx will truncate proxied responses at about 32k because buffering is on, and that's the default size.

We can add "proxy_buffering off;" to the config - but it cannot be in the global context, so we can't just append it to the config file in the nginx-proxy dockerfile (fatal error - I tried) - it needs to be in the context of the proxy, and so needs to be added to the template docker-gen is using.

I was going to fork this and add it and get go and godeps and the glavin - and realized it's likely you can patch this faster than I could rebuild it to confirm.

Volumes metadata?

Is it possible to get metadata on the available volumes to a container? I'd love to use this in a similar fashion as the nginx-proxy image. But to instead serve static paths based on volumes passed with --volumes-from.

Use labels instead of environment variables

The latest version of docker let's you label a container with metadata, associating a string value to a string key. This seems like a better fit for VIRTUAL_HOST than using environment variables

forward stdout/stderr of -notify command

forward stdout/stderr of -notify command
This can greatly help when things go wrong. E.g when your command is -notify "nginx -s reload" and for some reason there is a syntax error in the generated config. Then you'd get the error from nginx directly and would not have to dive into the container to debug.

Accessing Local Container Variables In Template

I've been looking though your examples but am fairly certain this use case isn't covered:
Is it possible to retrieve environmental variables from the running container?

For example, if I start the container with "docker run -e TEMP=hello ..." and then run docker-gen inside it, is it possible to echo out the value of TEMP without wastefully looping through every running container?

Thanks for your time, this project is seriously one of the neatest Docker tools I've found ;)

unable to parse template: template: docker-gen:2208: unexpected unrecognized character in action: U+0000 in command

Hi,
I am not sure if this issue is related to docker-gen.
When I try to run your examples with http://fig.sh I get the following error message:

dockergen_1 | 2014/12/21 14:14:37 unable to parse template: template: docker-gen:2208: 
unexpected unrecognized character in action: U+0000 in command

My fig.yml looks like this:

    nginx:
      image: nginx
      volumes:
        - /tmp/nginx:/etc/nginx/conf.d
      ports:
        - "80:80"

    dockergen:
      image: jwilder/docker-gen:0.3.6
      command: /usr/local/bin/docker-gen -notify-sighup nginx -watch --only-published /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
      volumes:
        - /var/run/docker.sock:/tmp/docker.sock
        - /tmp/templates:/etc/docker-gen/templates
      volumes_from:
        - nginx

Ideas?

Must pass an array or slice to 'whereExist'

Hi,

What am I doing wrong?

$ docker run --rm -ti jwilder/docker-gen -version
0.4.0

logstash-forwarder.json.tmpl:

{{whereExist . "Labels.logs" | len}}
$ docker run --rm -ti -v `pwd`/templates:/templates -v /var/run/docker.sock:/tmp/docker.sock jwilder/docker-gen -watch /templates/logstash-forwarder.json.tmpl /etc/logstash-forwarder.json
2015/07/16 07:13:41 template error: template: logstash-forwarder.json.tmpl:1:2: executing "logstash-forwarder.json.tmpl" at <whereExist . "Labels...>: error calling whereExist: Must pass an array or slice to 'whereExist'; received &[0xc208000d80 0xc208001560 0xc2080017a0 0xc208001c20 0xc2080a2120 0xc2080a2360 0xc2080a26c0 0xc2080a2b40 0xc2080a2fc0]

Support for communicating with Docker over TCP

I'm trying to set up the nginx reverse proxy as a docker container.

To do that, it'd be nice if docker-gen supported the DOCKER_HOST environment variable or a command-line parameter specifying how to communicate with Docker.

Support for multiple DOCKER_HOST?

It'd be really convenient if docker-gen could support multiple (comma-separated?) values in DOCKER_HOST environment variable to be able to cleanly generate load balancer configs in a setup where backends are on different hosts.

Currently https://github.com/jwilder/docker-register & https://github.com/jwilder/docker-discover kinda do the trick but has some limitations:

  1. No SPDY support in HAProxy (which could be a deal breaker for many production systems).
  2. There is no way to access more properties of remote containers unless docker-register somehow adds these keys in etcd.

I am currently working on the following forks to overcome above limitations, but I'm already feeling dirty now:

  1. docker-register that registers all container ENVs with etcd
  2. docker-discover that replaces HAProxy with Nginx using VIRTUAL_HOST from ENVs in etcd and nginx template from https://github.com/jwilder/nginx-proxy

However, if we can add support for multiple DOCKER_HOSTs, life will be super easy; I can just use jwilder/nginx-proxy without having to do etcd+register+discover.

PS: I'd rather implement this feature then do the 2 forks described above. I'd love second opinion on the idea before I can start working.

Argument order for split and replace

It's probably too late to change this, but after playing around with text/template and looking at the functions used in Hugo, I feel like the argument order for split and replace in docker-gen (and dockerize) should be flipped.

In particular, I don't think that split $string $sep works well with the pipeline semantics common to the built-in text/template functions. It would be nice to be able to do this:

{{ $domain := index $container.Env "VIRTUAL_HOST" | split "," | first | split "." | last }}

As it stands, you need to do this instead:

{{ $domain := last (split (first (split (index $container.Env "VIRTUAL_HOST") ",")) ".") }}

(Ignore that first doesn't exist; it could be easily implemented)

Error using example etcd template

2014/06/03 10:35:06 template error: template: etcd.tmpl:4:20: executing "etcd.tmpl" at <index $value.Address...>: error calling index: index out of range: 0

Question: Config File, Multiple Functions, Daemonize

Have you considered modifying this application to use a config file (yaml, json, ini format) that can define multiple actions that this can take.

I have a use case for generating logrotate, splunk monitor logs, and populate nginx configs at all the same time.

Also have you considering daemonizing the application so it can be run by systemd or upstart?

Thanks for the tool, I just submitted PR, I'm all for contributing, but what I'm talking about above are major changes and thought it would be best to discuss with you.

Local environment variables in loops work once

I've got the following template for a logrotate setup:

{{ range $index, $value := $ }}
/var/lib/docker/containers/{{ $value.ID }}/{{ $value.ID }}-json.log
{
    {{ .Env.LOGROTATE_MODE }}
    missingok
    rotate {{ .Env.LOGROTATE_ROTATE }}
    size {{ .Env.LOGROTATE_SIZE }}
    compress
    notifempty
    copytruncate
}
{{ end }}

and the result after running docker-gen is:

/var/lib/docker/containers/8c8...3f1-json.log
{
    daily
    missingok
    rotate 3
    size 512M
    compress
    notifempty
    copytruncate
}

/var/lib/docker/containers/b02...fa4-json.log
{
    <no value>
    missingok
    rotate <no value>
    size <no value>
    compress
    notifempty
    copytruncate
}

/var/lib/docker/containers/3ab...a37-json.log
{
    <no value>
    missingok
    rotate <no value>
    size <no value>
    compress
    notifempty
    copytruncate
}

I would expect that values will appear everywhere, is it expected behavior?

In my case I've already changed that template to loop only over the file paths, leaving brackets section outside. It's working now, but I think mentioned issue could be a problem in other templates.

docker-gen on Cluster

Does anyone have any knowledge of if it's possible to run docker-gem monitoring a cluster, possibly using Swarm?

Add a way to filter out containers in templates

Just following the last sentence from README (TODO).

Current set of functions allowed in templates is very limited and does not allow much filtering.

Even subset from following functions would help:

  • equality of strings
  • test, if a string is present in an array of string (for this we need also a function to define in template the array of string)
  • wildcard matching
  • startsWith

let -notify= send commands on the docker API

I'd like to keep docker-gen running in its own container, seeing as it already has access to the docker API, could docker-gen support a kill -s HUP or a restart on the docker API?

This way, we can just put the templates in a shared volume, and restart / kill -HUP a container running from that config.

Allow -notify-sigup to work with docker-compose

In a docker-compose situation, the container name isn't known in advance. A way to tell -notify-sigup to pull the container name from an environment variable (ie $nginx_NAME) would be helpful.

After more reading, I might be misunderstanding how docker-compose sets the environment variables.

I'm looking for a solution to putting docker-gen in a separate container from nginx and still being able to use -notify-sigup on the container which gets turned into _nginx_1 and not really known ahead of time (unless you assume how docker-compose is going to name the containers).

This might get solved in a future release when docker-compose includes the ability to name your containers whatever you'd like.

Separate config per container

Is there any possibility to define a separate template for each container separately?
For example I have one host with many containers and some containers need different templates (some, with SSL, some without, some with extra options defined)

"default" helper

Hi,

I'm missing a helper that can return a default value of a given value is empty. For example:

{{.Env.VIRTUAL_HOST | default "example.com"}}

The helper can be implemented as follows, but I'm not sure it's the best implementation:

// defaultHelper returns the first argument if no second argument given
// otherwise returhs second argument
func defaultHelper(defaultVal interface{}, actualValue ...interface{}) interface{} {
    if len(actualValue) > 0 {
        return actualValue[0]
    } else {
        return defaultVal
    }
}

Release schedule

Do you have any idea on when you will release another version, especially with the recent changes? Thanks! Mainly looking to take advantage of having SaltStack download from the github release page.

--only-exposed=true is ignored

generateFile() does this:

filteredContainers := []*RuntimeContainer{}
if config.OnlyExposed {
    for _, container := range containers {
        if len(container.Addresses) > 0 {
            filteredContainers = append(filteredContainers, container)
        }
    }
} else {
    filteredContainers = containers
}

but then generates the template using the unfiltered containers:

err = tmpl.ExecuteTemplate(multiwriter, filepath.Base(templatePath), containers)

Darwin build

Once #33 is sorted out, I'd love to see an official Darwin build of docker-gen. I've built it myself locally, so I can say that it definitely works and can be trivially added to the release build process.

Describe available data structures and functions for authoring templates

Trying to author my own templates (and not being Golang programmer), I have difficulties to find, what attributes are usable and what not.

Currently, there are only sample templates, which are helping, but one gets feeling much more is possible.

Describe available data structures

Point to some API spec, data structures in this project or in go-dockerclient, or anywhere, where I can find, what data model is available.

Trying to find what structures to expect I got lost.

Few hints to what attributes are mostly present and which might be missing (causing rendering the output to fail) would help.

Describe available functions

This seems easier (but still requires diving into code).

https://github.com/jwilder/docker-gen/blob/2fe6ff54f222b06079fd446a84f9976e28b303f1/template.go#L61 shows there are following functions available:

  • "contains"
  • "exists"
  • "groupBy"
  • "groupByMulti"
  • "split"

Short example for groupByMlti and GroupBy would be nice.

Conclusions

It is likely, that with Golang knowledge the information can be found. However, this tools is generally very useful and with proposed templating instructions could serve many more users, who are not proficient in Golang.

zsh: exec format error: ./docker-gen

I downloaded both i386 and amd64, extracted it and running give error:

zsh: exec format error: ./docker-gen

I'm using zsh:

$ zsh --version
zsh 5.0.5 (x86_64-apple-darwin13.0.0)

Notify throttling

Hi,
It would be nice to have some kind of configurable notification delay. For example, if I run 10 containers in a row within a second, it generates dozens of events and each will cause SIGHUP notify or equivalent.

With 5 seconds delay, docker-gen may wait and then notify only once.

I can contribute this functionality after you confirm the feature is needed and will be accepted.

Support generating content for stopped containers

Please enable a possibility to generate template instances for stopped containers, not just running ones.
This could come in a form of a flag for docker-gen, -also-stopped-containers, for example. This is equivalent to the -a flag of docker ps.

The main use-case is when generating a fluentd configuration file. The best practice is to regenerate the configuration file and restart fluentd. However consider what happens to a short-lived container, one that crashes seconds after it starts. On receiving the stop event, the fluentd configuration file will no longer refer to that container, and logs from this container will probably be lost.

log ?

Is there a way to have docker-gen -watch produce logs when run from supervisord?

-endpoint works differently depending on presence of -watch flag

When the container is started, the instructions suggest -v /var/run/docker.sock:/tmp/docker.sock. The following is a non issue if one uses -v /var/run/docker.sock:/var/run/docker.sock instead. Since the instructions suggest otherwise, I think I should report this behavior.

Note that this is a Docker image based off of FROM tianon/centos:6.5.

Without -watch, /tmp/docker.sock is needed.

bash-4.1# ./docker-gen -endpoint unix://tmp/docker.sock templates/some.tmpl some.out
2014/07/10 14:38:20 error listing containers: dial unix /docker.sock: no such file or directory

bash-4.1# ./docker-gen -endpoint unix:/tmp/docker.sock templates/some.tmpl some.out
2014/07/10 14:38:25 Generated 'some.out' from 5 containers

With -watch, ///tmp/docker.sock is needed.

bash-4.1# ./docker-gen -watch -endpoint unix:/tmp/docker.sock templates/some.tmpl some.out
2014/07/10 14:38:59 Contents of some.out did not change. Skipping notification ''
2014/07/10 14:38:59 Watching docker events
2014/07/10 14:38:59 cannot connect to docker: Invalid bind address format: unix:/tmp/docker.sock

bash-4.1# ./docker-gen -watch -endpoint unix://tmp/docker.sock templates/some.tmpl some.out
2014/07/10 14:39:08 error listing containers: dial unix /docker.sock: no such file or directory
2014/07/10 14:39:08 Watching docker events
2014/07/10 14:39:08 cannot connect to docker: dial unix tmp/docker.sock: no such file or directory

bash-4.1# ./docker-gen -watch -endpoint unix:///tmp/docker.sock templates/some.tmpl some.out
2014/07/10 14:39:16 Contents of some.out did not change. Skipping notification ''
2014/07/10 14:39:16 Watching docker events

install error

Can you help me debug this error durring install?

root@docker:~# go get github.com/jwilder/docker-gen
# github.com/BurntSushi/toml
/usr/lib/go/src/pkg/github.com/BurntSushi/toml/encode.go:248: function ends without a return statement
/usr/lib/go/src/pkg/github.com/BurntSushi/toml/encode.go:276: function ends without a return statement
/usr/lib/go/src/pkg/github.com/BurntSushi/toml/encode.go:430: function ends without a return statement
/usr/lib/go/src/pkg/github.com/BurntSushi/toml/encode.go:461: function ends without a return statement
/usr/lib/go/src/pkg/github.com/BurntSushi/toml/encode.go:499: function ends without a return statement
/usr/lib/go/src/pkg/github.com/BurntSushi/toml/lex.go:71: function ends without a return statement
# github.com/fsouza/go-dockerclient/utils
/usr/lib/go/src/pkg/github.com/fsouza/go-dockerclient/utils/utils.go:785: undefined: strings.TrimPrefix
/usr/lib/go/src/pkg/github.com/fsouza/go-dockerclient/utils/utils.go:791: undefined: strings.TrimPrefix

Release!

Just got hit by the bug fixed by 4de4160 - would you mind cutting a new release?

Add check option

It would be good to be able to run a check command before running notify command to ensure that the generated file is valid. For example, being able to run nginx -t before runing nginx reload would help prevent errors such as nginx-proxy/nginx-proxy#107

Generate multiple files at once

Hi @jwilder,

I was toying around with the idea of a Docker container that starts an avahi daemon with configuration generated from other containers (much like nginx-proxy)

So for example, to announce samba through avahi we could simply:

$ docker run -e SERVICE_NAME=MySambaServer nunofgs/samba

The problem is that avahi requires that services be added individually to the /etc/avahi/services/ folder but docker-gen only outputs one file.

Is there any way to use docker-gen to generate multiple files at once?

panic: runtime error: slice bounds out of range

I have the following error on a fresh install (Ubuntu 14.04 64bit, docker 0.10.0)

panic: runtime error: slice bounds out of range

goroutine 1 [running]:
runtime.panic(0x6a9cc0, 0xa270aa)
    /usr/lib/go/src/pkg/runtime/panic.c:266 +0xb6
main.splitDockerImage(0xc21006e3c0, 0x20, 0x40, 0xc2100489a0, 0x0, ...)
    GOPATH/src/github.com/jwilder/docker-gen/docker-gen.go:80 +0x251
main.getContainers(0xc2100524a0, 0xa3512c, 0x7f358b492d20, 0x7, 0x7fff53dd87de, ...)
    GOPATH/src/github.com/jwilder/docker-gen/docker-gen.go:203 +0x3ca
main.generateFromContainers(0xc2100524a0)
    GOPATH/src/github.com/jwilder/docker-gen/docker-gen.go:233 +0x35
main.main()
    GOPATH/src/github.com/jwilder/docker-gen/docker-gen.go:357 +0x3bd

goroutine 3 [syscall]:
os/signal.loop()
    /usr/lib/go/src/pkg/os/signal/signal_unix.go:21 +0x1e
created by os/signal.init·1
    /usr/lib/go/src/pkg/os/signal/signal_unix.go:27 +0x31

I can always repoduce the error, however it seems like that the same method works on my other computer with the same fresh OS & docker install.

If you need more info, let me know.

Please help me fixing it! Thanks!

TLS_VERIFY= ignored in 0.4.0

I am using boot2docker on Mac OS X. You can reproduce this by building jwilder/nginx-proxy with 0.4.0

[~/src/nginx-proxy] [git:master]
keegan@cliche $ boot2docker version
Boot2Docker-cli version: v1.6.2
Git commit: cb2c3bc
[~/src/nginx-proxy] [git:master]
keegan@cliche $ docker version
Client version: 1.6.2
Client API version: 1.18
Go version (client): go1.4.2
Git commit (client): 7c8fca2
OS/Arch (client): darwin/amd64
Server version: 1.6.2
Server API version: 1.18
Go version (server): go1.4.2
Git commit (server): 7c8fca2
OS/Arch (server): linux/amd64
[~/src/nginx-proxy] [git:master]
keegan@cliche $ boot2docker shellinit 2> /dev/null
    export DOCKER_CERT_PATH=/Users/keegan/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1
    export DOCKER_HOST=tcp://192.168.59.103:2376
[~/src/nginx-proxy] [git:master]
keegan@cliche $ docker run -e DOCKER_HOST="$DOCKER_HOST" -e DOCKER_TLS_VERIFY= -p 80:80 jwilder/nginx-proxy:latest env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=30ee82fb4946
DOCKER_HOST=tcp://192.168.59.103:2376
DOCKER_TLS_VERIFY=
NGINX_VERSION=1.9.0-1~jessie
DOCKER_GEN_VERSION=0.4.0
HOME=/root
[~/src/nginx-proxy] [git:master]
keegan@cliche $ docker run -e DOCKER_HOST="$DOCKER_HOST" -e DOCKER_TLS_VERIFY= -p 80:80 jwilder/nginx-proxy:latest docker-gen -version
0.4.0
[~/src/nginx-proxy] [git:master]
keegan@cliche $ docker run -e DOCKER_HOST="$DOCKER_HOST" -e DOCKER_TLS_VERIFY= -p 80:80 jwilder/nginx-proxy:latest
forego     | starting nginx.1 on port 5000
forego     | starting dockergen.1 on port 5100
dockergen.1 | 2015/06/15 16:12:41 error listing containers: Get https://192.168.59.103:2376/containers/json: x509: certificate signed by unknown authority
dockergen.1 | 2015/06/15 16:12:41 Unable to ping docker daemon: Get https://192.168.59.103:2376/_ping: x509: certificate signed by unknown authority
^C      | ctrl-c detected
forego     | sending SIGTERM to nginx.1
forego     | sending SIGTERM to dockergen.1
[~/src/nginx-proxy] [git:master]
keegan@cliche $

Race condition in -watch

We are using docker-gen in this dynamic DNS server: https://github.com/ncarlier/dockerfiles/tree/master/dnsmasq. This requires that the DNS configuration is updated when docker-gen is started, and whenever containers are started and stopped thereafter. Unfortunately, there is a gap between the initial update and the point where docker-gen starts watching for events, as shown in this log:

2015-02-11 18:45:42,946 INFO spawned: 'docker-gen' with pid 9
2015-02-11 18:45:43,001 INFO spawned: 'dnsmasq' with pid 10
2015/02/11 18:45:43 Generated '/etc/dnsmasq.conf' from 4 containers
2015/02/11 18:45:43 Running 'supervisorctl restart dnsmasq'
[...]
2015/02/11 18:45:45 Watching docker events

Any containers started during that 2-second window will not appear in DNS until the next docker event, which may be an indefinite period of time.

Solution: docker-gen should start watching for events before its initial update.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.