Skip to content

Commit

Permalink
Merge pull request #3788 from hashicorp/f-entrypoint
Browse files Browse the repository at this point in the history
Allow overriding an image's entrypoint in Docker
  • Loading branch information
dadgar committed Jan 23, 2018
2 parents acd70e5 + 0cf5c76 commit 84ea89e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 2 deletions.
6 changes: 6 additions & 0 deletions client/driver/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ type DockerDriverConfig struct {
LoadImage string `mapstructure:"load"` // LoadImage is a path to an image archive file
Command string `mapstructure:"command"` // The Command to run when the container starts up
Args []string `mapstructure:"args"` // The arguments to the Command
Entrypoint []string `mapstructure:"entrypoint"` // Override the containers entrypoint
IpcMode string `mapstructure:"ipc_mode"` // The IPC mode of the container - host and none
NetworkMode string `mapstructure:"network_mode"` // The network mode of the container - host, nat and none
NetworkAliases []string `mapstructure:"network_aliases"` // The network-scoped alias for the container
Expand Down Expand Up @@ -299,6 +300,7 @@ func NewDockerDriverConfig(task *structs.Task, env *env.TaskEnv) (*DockerDriverC
// Interpolate everything that is a string
dconf.ImageName = env.ReplaceEnv(dconf.ImageName)
dconf.Command = env.ReplaceEnv(dconf.Command)
dconf.Entrypoint = env.ParseAndReplace(dconf.Entrypoint)
dconf.IpcMode = env.ReplaceEnv(dconf.IpcMode)
dconf.NetworkMode = env.ReplaceEnv(dconf.NetworkMode)
dconf.NetworkAliases = env.ParseAndReplace(dconf.NetworkAliases)
Expand Down Expand Up @@ -559,6 +561,9 @@ func (d *DockerDriver) Validate(config map[string]interface{}) error {
"args": {
Type: fields.TypeArray,
},
"entrypoint": {
Type: fields.TypeArray,
},
"ipc_mode": {
Type: fields.TypeString,
},
Expand Down Expand Up @@ -1070,6 +1075,7 @@ func (d *DockerDriver) createContainerConfig(ctx *ExecContext, task *structs.Tas
// create the config block that will later be consumed by go-dockerclient
config := &docker.Config{
Image: d.imageID,
Entrypoint: driverConfig.Entrypoint,
Hostname: driverConfig.Hostname,
User: task.User,
Tty: driverConfig.TTY,
Expand Down
31 changes: 29 additions & 2 deletions client/driver/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/hashicorp/nomad/nomad/structs"
tu "github.com/hashicorp/nomad/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func dockerIsRemote(t *testing.T) bool {
Expand Down Expand Up @@ -106,13 +107,14 @@ func testDockerDriverContexts(t *testing.T, task *structs.Task) *testContext {
func dockerSetupWithClient(t *testing.T, task *structs.Task, client *docker.Client) (*docker.Client, *DockerHandle, func()) {
t.Helper()
tctx := testDockerDriverContexts(t, task)
//tctx.DriverCtx.config.Options = map[string]string{"docker.cleanup.image": "false"}
driver := NewDockerDriver(tctx.DriverCtx)
copyImage(t, tctx.ExecCtx.TaskDir, "busybox.tar")

presp, err := driver.Prestart(tctx.ExecCtx, task)
if err != nil {
driver.Cleanup(tctx.ExecCtx, presp.CreatedResources)
if presp != nil && presp.CreatedResources != nil {
driver.Cleanup(tctx.ExecCtx, presp.CreatedResources)
}
tctx.AllocDir.Destroy()
t.Fatalf("error in prestart: %v", err)
}
Expand Down Expand Up @@ -2171,7 +2173,32 @@ func TestDockerDriver_Device_Success(t *testing.T) {

assert.NotEmpty(t, container.HostConfig.Devices, "Expected one device")
assert.Equal(t, expectedDevice, container.HostConfig.Devices[0], "Incorrect device ")
}

func TestDockerDriver_Entrypoint(t *testing.T) {
if !tu.IsTravis() {
t.Parallel()
}
if !testutil.DockerIsConnected(t) {
t.Skip("Docker not connected")
}

entrypoint := []string{"/bin/sh", "-c"}
task, _, _ := dockerTask(t)
task.Config["entrypoint"] = entrypoint

client, handle, cleanup := dockerSetup(t, task)
defer cleanup()

waitForExist(t, client, handle)

container, err := client.InspectContainer(handle.ContainerID())
if err != nil {
t.Fatalf("err: %v", err)
}

require.Len(t, container.Config.Entrypoint, 2, "Expected one entrypoint")
require.Equal(t, entrypoint, container.Config.Entrypoint, "Incorrect entrypoint ")
}

func TestDockerDriver_Kill(t *testing.T) {
Expand Down
4 changes: 4 additions & 0 deletions client/driver/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ func (t *TaskEnv) All() map[string]string {
// ParseAndReplace takes the user supplied args replaces any instance of an
// environment variable or Nomad variable in the args with the actual value.
func (t *TaskEnv) ParseAndReplace(args []string) []string {
if args == nil {
return nil
}

replaced := make([]string, len(args))
for i, arg := range args {
replaced[i] = hargs.ReplaceEnv(arg, t.EnvMap, t.NodeAttrs)
Expand Down
2 changes: 2 additions & 0 deletions website/source/docs/drivers/docker.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ The `docker` driver supports the following configuration in the job spec. Only
* `dns_servers` - (Optional) A list of DNS servers for the container to use
(e.g. ["8.8.8.8", "8.8.4.4"]). Requires Docker v1.10 or greater.

* `entrypoint` - (Optional) A string list overriding the image's entrypoint.

* `extra_hosts` - (Optional) A list of hosts, given as host:IP, to be added to
`/etc/hosts`.

Expand Down

0 comments on commit 84ea89e

Please sign in to comment.