Skip to content

Commit

Permalink
Merge pull request #476 from hashicorp/b-docker-expose
Browse files Browse the repository at this point in the history
Fixed some issues with expose, port mapping, and environment variables
  • Loading branch information
cbednarski committed Nov 20, 2015
2 parents b00537f + c298425 commit 61aeace
Show file tree
Hide file tree
Showing 7 changed files with 310 additions and 146 deletions.
9 changes: 5 additions & 4 deletions client/consul.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package client

import (
"fmt"
consul "github.com/hashicorp/consul/api"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/nomad/nomad/structs"
"log"
"net/url"
"sync"
"time"

consul "github.com/hashicorp/consul/api"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/nomad/nomad/structs"
)

const (
Expand Down Expand Up @@ -95,7 +96,7 @@ func (c *ConsulClient) ShutDown() {

func (c *ConsulClient) findPortAndHostForLabel(portLabel string, task *structs.Task) (string, int) {
for _, network := range task.Resources.Networks {
if p, ok := network.MapLabelToValues()[portLabel]; ok {
if p, ok := network.MapLabelToValues(nil)[portLabel]; ok {
return network.IP, p
}
}
Expand Down
53 changes: 30 additions & 23 deletions client/driver/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ type DockerDriverConfig struct {
Command string `mapstructure:"command"` // The Command/Entrypoint to run when the container starts up
Args []string `mapstructure:"args"` // The arguments to the Command/Entrypoint
NetworkMode string `mapstructure:"network_mode"` // The network mode of the container - host, net and none
PortMap []map[string]int `mapstructure:"port_map"` // A map of host port labels and the ports exposed on the container
PortMapRaw []map[string]int `mapstructure:"port_map"` //
PortMap map[string]int `mapstructure:"-"` // A map of host port labels and the ports exposed on the container
Privileged bool `mapstructure:"privileged"` // Flag to run the container in priviledged mode
DNSServers []string `mapstructure:"dns_servers"` // DNS Server for containers
DNSSearchDomains []string `mapstructure:"dns_search_domains"` // DNS Search domains for containers
Hostname string `mapstructure:"hostname"` // Hostname for containers
Labels []map[string]string `mapstructure:"labels"` // Labels to set when the container starts up
LabelsRaw []map[string]string `mapstructure:"labels"` //
Labels map[string]string `mapstructure:"-"` // Labels to set when the container starts up
Auth []DockerDriverAuth `mapstructure:"auth"` // Authentication credentials for a private Docker registry
}

Expand All @@ -51,13 +53,9 @@ func (c *DockerDriverConfig) Validate() error {
return fmt.Errorf("Docker Driver needs an image name")
}

if len(c.PortMap) > 1 {
return fmt.Errorf("Only one port_map block is allowed in the docker driver config")
}
c.PortMap = mapMergeStrInt(c.PortMapRaw...)
c.Labels = mapMergeStrStr(c.LabelsRaw...)

if len(c.Labels) > 1 {
return fmt.Errorf("Only one labels block is allowed in the docker driver config")
}
return nil
}

Expand Down Expand Up @@ -239,7 +237,7 @@ func (d *DockerDriver) createContainer(ctx *ExecContext, task *structs.Task, dri
// Setup port mapping and exposed ports
if len(task.Resources.Networks) == 0 {
d.logger.Println("[DEBUG] driver.docker: No network interfaces are available")
if len(driverConfig.PortMap) == 1 && len(driverConfig.PortMap[0]) > 0 {
if len(driverConfig.PortMap) > 0 {
return c, fmt.Errorf("Trying to map ports but no network interface is available")
}
} else {
Expand All @@ -249,8 +247,16 @@ func (d *DockerDriver) createContainer(ctx *ExecContext, task *structs.Task, dri
exposedPorts := map[docker.Port]struct{}{}

for _, port := range network.ReservedPorts {
// By default we will map the allocated port 1:1 to the container
containerPortInt := port.Value

// If the user has mapped a port using port_map we'll change it here
if mapped, ok := driverConfig.PortMap[port.Label]; ok {
containerPortInt = mapped
}

hostPortStr := strconv.Itoa(port.Value)
containerPort := docker.Port(hostPortStr)
containerPort := docker.Port(strconv.Itoa(containerPortInt))

publishedPorts[containerPort+"/tcp"] = []docker.PortBinding{docker.PortBinding{HostIP: network.IP, HostPort: hostPortStr}}
publishedPorts[containerPort+"/udp"] = []docker.PortBinding{docker.PortBinding{HostIP: network.IP, HostPort: hostPortStr}}
Expand All @@ -261,21 +267,16 @@ func (d *DockerDriver) createContainer(ctx *ExecContext, task *structs.Task, dri
d.logger.Printf("[DEBUG] driver.docker: exposed port %d", port.Value)
}

containerToHostPortMap := make(map[string]int)
for _, port := range network.DynamicPorts {
// By default we will map the allocated port 1:1 to the container
containerPortInt := port.Value

// If the user has mapped a port using port_map we'll change it here
if len(driverConfig.PortMap) == 1 {
mapped, ok := driverConfig.PortMap[0][port.Label]
if ok {
containerPortInt = mapped
}
if mapped, ok := driverConfig.PortMap[port.Label]; ok {
containerPortInt = mapped
}

hostPortStr := strconv.Itoa(port.Value)
// containerPort := docker.Port(hostPortStr)
containerPort := docker.Port(strconv.Itoa(containerPortInt))

publishedPorts[containerPort+"/tcp"] = []docker.PortBinding{docker.PortBinding{HostIP: network.IP, HostPort: hostPortStr}}
Expand All @@ -284,12 +285,18 @@ func (d *DockerDriver) createContainer(ctx *ExecContext, task *structs.Task, dri

exposedPorts[containerPort+"/tcp"] = struct{}{}
exposedPorts[containerPort+"/udp"] = struct{}{}
d.logger.Printf("[DEBUG] driver.docker: exposed port %s", hostPortStr)

containerToHostPortMap[string(containerPort)] = port.Value
d.logger.Printf("[DEBUG] driver.docker: exposed port %s", containerPort)
}

env.SetPorts(containerToHostPortMap)
// This was set above in a call to TaskEnvironmentVariables but if we
// have mapped any ports we will need to override them.
//
// TODO refactor the implementation in TaskEnvironmentVariables to match
// the 0.2 ports world view. Docker seems to be the only place where
// this is actually needed, but this is kinda hacky.
if len(driverConfig.PortMap) > 0 {
env.SetPorts(network.MapLabelToValues(driverConfig.PortMap))
}
hostConfig.PortBindings = publishedPorts
config.ExposedPorts = exposedPorts
}
Expand All @@ -309,8 +316,8 @@ func (d *DockerDriver) createContainer(ctx *ExecContext, task *structs.Task, dri
d.logger.Println("[DEBUG] driver.docker: ignoring command arguments because command is not specified")
}

if len(driverConfig.Labels) == 1 {
config.Labels = driverConfig.Labels[0]
if len(driverConfig.Labels) > 0 {
config.Labels = driverConfig.Labels
d.logger.Printf("[DEBUG] driver.docker: applied labels on the container: %+v", config.Labels)
}

Expand Down
Loading

0 comments on commit 61aeace

Please sign in to comment.