Преглед изворни кода

Merge pull request #1086 from crosbymichael/1008-image-entrypoint

+ Builder: Add Entrypoint to builder and container config
Guillaume J. Charmes пре 12 година
родитељ
комит
185a2fc55e
8 измењених фајлова са 90 додато и 4 уклоњено
  1. 13 2
      builder.go
  2. 18 1
      buildfile.go
  3. 9 0
      buildfile_test.go
  4. 8 0
      container.go
  5. 26 0
      container_test.go
  6. 1 0
      docs/sources/commandline/command/run.rst
  7. 7 0
      docs/sources/use/builder.rst
  8. 8 1
      utils.go

+ 13 - 2
builder.go

@@ -50,12 +50,23 @@ func (builder *Builder) Create(config *Config) (*Container, error) {
 		config.Hostname = id[:12]
 	}
 
+	var args []string
+	var entrypoint string
+
+	if len(config.Entrypoint) != 0 {
+		entrypoint = config.Entrypoint[0]
+		args = append(config.Entrypoint[1:], config.Cmd...)
+	} else {
+		entrypoint = config.Cmd[0]
+		args = config.Cmd[1:]
+	}
+
 	container := &Container{
 		// FIXME: we should generate the ID here instead of receiving it as an argument
 		ID:              id,
 		Created:         time.Now(),
-		Path:            config.Cmd[0],
-		Args:            config.Cmd[1:], //FIXME: de-duplicate from config
+		Path:            entrypoint,
+		Args:            args, //FIXME: de-duplicate from config
 		Config:          config,
 		Image:           img.ID, // Always use the resolved image id
 		NetworkSettings: &NetworkSettings{},

+ 18 - 1
buildfile.go

@@ -141,7 +141,7 @@ func (b *buildFile) CmdEnv(args string) error {
 func (b *buildFile) CmdCmd(args string) error {
 	var cmd []string
 	if err := json.Unmarshal([]byte(args), &cmd); err != nil {
-		utils.Debugf("Error unmarshalling: %s, using /bin/sh -c", err)
+		utils.Debugf("Error unmarshalling: %s, setting cmd to /bin/sh -c", err)
 		cmd = []string{"/bin/sh", "-c", args}
 	}
 	if err := b.commit("", cmd, fmt.Sprintf("CMD %v", cmd)); err != nil {
@@ -165,6 +165,23 @@ func (b *buildFile) CmdCopy(args string) error {
 	return fmt.Errorf("COPY has been deprecated. Please use ADD instead")
 }
 
+func (b *buildFile) CmdEntrypoint(args string) error {
+	if args == "" {
+		return fmt.Errorf("Entrypoint cannot be empty")
+	}
+
+	var entrypoint []string
+	if err := json.Unmarshal([]byte(args), &entrypoint); err != nil {
+		b.config.Entrypoint = []string{"/bin/sh", "-c", args}
+	} else {
+		b.config.Entrypoint = entrypoint
+	}
+	if err := b.commit("", b.config.Cmd, fmt.Sprintf("ENTRYPOINT %s", args)); err != nil {
+		return err
+	}
+	return nil
+}
+
 func (b *buildFile) addRemote(container *Container, orig, dest string) error {
 	file, err := utils.Download(orig, ioutil.Discard)
 	if err != nil {

+ 9 - 0
buildfile_test.go

@@ -79,6 +79,15 @@ run [ "$(cat /somewheeeere/over/the/rainbooow/ga)" = "bu" ]
 from %s
 env    FOO BAR
 run    [ "$FOO" = "BAR" ]
+`,
+		nil,
+	},
+
+	{
+		`
+from docker-ut
+ENTRYPOINT /bin/echo
+CMD Hello world
 `,
 		nil,
 	},

+ 8 - 0
container.go

@@ -76,6 +76,7 @@ type Config struct {
 	Image        string // Name of the image as it was passed by the operator (eg. could be symbolic)
 	Volumes      map[string]struct{}
 	VolumesFrom  string
+	Entrypoint   []string
 }
 
 type HostConfig struct {
@@ -123,6 +124,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
 	cmd.Var(flVolumes, "v", "Attach a data volume")
 
 	flVolumesFrom := cmd.String("volumes-from", "", "Mount volumes from the specified container")
+	flEntrypoint := cmd.String("entrypoint", "", "Overwrite the default entrypoint of the image")
 
 	var flBinds ListOpts
 	cmd.Var(&flBinds, "b", "Bind mount a volume from the host (e.g. -b /host:/container)")
@@ -153,6 +155,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
 
 	parsedArgs := cmd.Args()
 	runCmd := []string{}
+	entrypoint := []string{}
 	image := ""
 	if len(parsedArgs) >= 1 {
 		image = cmd.Arg(0)
@@ -160,6 +163,10 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
 	if len(parsedArgs) > 1 {
 		runCmd = parsedArgs[1:]
 	}
+	if *flEntrypoint != "" {
+		entrypoint = []string{*flEntrypoint}
+	}
+
 	config := &Config{
 		Hostname:     *flHostname,
 		PortSpecs:    flPorts,
@@ -177,6 +184,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
 		Image:        image,
 		Volumes:      flVolumes,
 		VolumesFrom:  *flVolumesFrom,
+		Entrypoint:   entrypoint,
 	}
 	hostConfig := &HostConfig{
 		Binds: flBinds,

+ 26 - 0
container_test.go

@@ -1043,6 +1043,32 @@ func TestEnv(t *testing.T) {
 	}
 }
 
+func TestEntrypoint(t *testing.T) {
+	runtime, err := newTestRuntime()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer nuke(runtime)
+	container, err := NewBuilder(runtime).Create(
+		&Config{
+			Image:      GetTestImage(runtime).ID,
+			Entrypoint: []string{"/bin/echo"},
+			Cmd:        []string{"-n", "foobar"},
+		},
+	)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer runtime.Destroy(container)
+	output, err := container.Output()
+	if err != nil {
+		t.Fatal(err)
+	}
+	if string(output) != "foobar" {
+		t.Error(string(output))
+	}
+}
+
 func grepFile(t *testing.T, path string, pattern string) {
 	f, err := os.Open(path)
 	if err != nil {

+ 1 - 0
docs/sources/commandline/command/run.rst

@@ -26,3 +26,4 @@
       -v=[]: Creates a new volume and mounts it at the specified path.
       -volumes-from="": Mount all volumes from the given container.
       -b=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]
+      -entrypoint="": Overwrite the default entrypoint set by the image.

+ 7 - 0
docs/sources/use/builder.rst

@@ -153,6 +153,13 @@ of `<src>` will be written at `<dst>`.
 If `<dest>` doesn't exist, it is created along with all missing directories in its path. All new
 files and directories are created with mode 0700, uid and gid 0.
 
+2.8 ENTRYPOINT
+-------------
+
+    ``ENTRYPOINT /bin/echo``
+
+The `ENTRYPOINT` instruction adds an entry command that will not be overwritten when arguments are passed to docker run, unlike the behavior of `CMD`.  This allows arguments to be passed to the entrypoint.  i.e. `docker run <image> -d` will pass the "-d" argument to the entrypoint.
+
 3. Dockerfile Examples
 ======================
 

+ 8 - 1
utils.go

@@ -44,7 +44,11 @@ func CompareConfig(a, b *Config) bool {
 			return false
 		}
 	}
-
+	for i := 0; i < len(a.Entrypoint); i++ {
+		if a.Entrypoint[i] != b.Entrypoint[i] {
+			return false
+		}
+	}
 	return true
 }
 
@@ -85,4 +89,7 @@ func MergeConfig(userConf, imageConf *Config) {
 	if userConf.Dns == nil || len(userConf.Dns) == 0 {
 		userConf.Dns = imageConf.Dns
 	}
+	if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
+		userConf.Entrypoint = imageConf.Entrypoint
+	}
 }