diff --git a/client/driver/docker.go b/client/driver/docker.go index bbd52a9d8a2..e9d0cb32e2b 100644 --- a/client/driver/docker.go +++ b/client/driver/docker.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "log" + "net" "path/filepath" "strconv" "strings" @@ -73,6 +74,15 @@ func (d *DockerDriver) Fingerprint(cfg *config.Config, node *structs.Node) (bool return false, nil } + privileged, err := strconv.ParseBool(d.config.ReadDefault("docker.privileged.enabled", "false")) + if err != nil { + return false, fmt.Errorf("Unable to parse docker.privileged.enabled: %s", err) + } + if privileged == true { + d.logger.Printf("[DEBUG] driver.docker: privileged containers enabled. Only enable if needed") + node.Attributes["docker.privileged.enabled"] = "1" + } + _, err = strconv.ParseBool(d.config.ReadDefault("docker.cleanup.container", "true")) if err != nil { return false, fmt.Errorf("Unable to parse docker.cleanup.container: %s", err) @@ -166,6 +176,38 @@ func (d *DockerDriver) createContainer(ctx *ExecContext, task *structs.Task) (do d.logger.Printf("[DEBUG] driver.docker: using %d cpu shares for %s", hostConfig.CPUShares, task.Config["image"]) d.logger.Printf("[DEBUG] driver.docker: binding directories %#v for %s", hostConfig.Binds, task.Config["image"]) + // set privileged mode + if v, ok := task.Config["privileged"]; ok { + taskPrivileged, err := strconv.ParseBool(v) + if err != nil { + return c, fmt.Errorf("Unable to parse boolean value from task config option 'privileged': %s", err) + } + hostConfig.Privileged = taskPrivileged + } + + // set DNS servers + dns, ok := task.Config["dns-servers"] + + if ok && dns != "" { + for _, v := range strings.Split(dns, ",") { + ip := strings.TrimSpace(v) + if net.ParseIP(ip) != nil { + hostConfig.DNS = append(hostConfig.DNS, ip) + } else { + d.logger.Printf("[ERR] driver.docker: invalid ip address for container dns server: %s", ip) + } + } + } + + // set DNS search domains + dnsSearch, ok := task.Config["search-domains"] + + if ok && dnsSearch != "" { + for _, v := range strings.Split(dnsSearch, ",") { + hostConfig.DNSSearch = append(hostConfig.DNSSearch, strings.TrimSpace(v)) + } + } + mode, ok := task.Config["network_mode"] if !ok || mode == "" { // docker default @@ -303,8 +345,14 @@ func (d *DockerDriver) Start(ctx *ExecContext, task *structs.Task) (DriverHandle Repository: repo, Tag: tag, } - // TODO add auth configuration for private repos - authOptions := docker.AuthConfiguration{} + + authOptions := docker.AuthConfiguration{ + Username: task.Config["auth.username"], + Password: task.Config["auth.password"], + Email: task.Config["auth.email"], + ServerAddress: task.Config["auth.server-address"], + } + err = client.PullImage(pullOptions, authOptions) if err != nil { d.logger.Printf("[ERR] driver.docker: pulling container %s", err) diff --git a/website/source/docs/drivers/docker.html.md b/website/source/docs/drivers/docker.html.md index 444e7f6cade..c24a171af7a 100644 --- a/website/source/docs/drivers/docker.html.md +++ b/website/source/docs/drivers/docker.html.md @@ -32,6 +32,26 @@ The `docker` driver supports the following configuration in the job specificatio network mode is not supported right now and is reported as an invalid option. +* `privileged` - (optional) Privileged mode gives the container full access to + the host. Valid options are `"true"` and `"false"` (defaults to `"false"`). + In order to use privileged mode, a client with the option + `docker.privileged.enabled = "true"` must be available. + +* `dns-servers` - (optional) A comma separated list of DNS servers for the container + to use (e.g. "8.8.8.8,8.8.4.4"). *Docker API v1.10 and above only* + +* `search-domains` - (optional) A comma separated list of DNS search domains for the + container to use. + +**Authentication** +Registry authentication can be set per task with the following authentication +parameters. These options can provide access to private repositories that +utilize the docker remote api (e.g. dockerhub, quay.io) + - `auth.username` - (optional) The account username + - `auth.password` - (optional) The account password + - `auth.email` - (optional) The account email + - `auth.server-address` - (optional) The server domain/ip without the protocol + ### Port Mapping Nomad uses port binding to expose services running in containers using the port @@ -121,6 +141,11 @@ The `docker` driver has the following configuration options: * `docker.cleanup.image` Defaults to `true`. Changing this to `false` will prevent Nomad from removing images from stopped tasks. +* `docker.privileged.enabled` Defaults to `false`. Changing this to `true` will + allow containers to use "privileged" mode, which gives the containers full access + to the host + + Note: When testing or using the `-dev` flag you can use `DOCKER_HOST`, `DOCKER_TLS_VERIFY`, and `DOCKER_CERT_PATH` to customize Nomad's behavior. In production Nomad will always read `docker.endpoint`.