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

+ Builder: Add Entrypoint to builder and container config
This commit is contained in:
Guillaume J. Charmes 2013-07-01 13:33:12 -07:00
commit 185a2fc55e
8 changed files with 90 additions and 4 deletions

View File

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

View File

@ -141,7 +141,7 @@ func (b *buildFile) CmdEnv(args string) error {
func (b *buildFile) CmdCmd(args string) error { func (b *buildFile) CmdCmd(args string) error {
var cmd []string var cmd []string
if err := json.Unmarshal([]byte(args), &cmd); err != nil { 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} cmd = []string{"/bin/sh", "-c", args}
} }
if err := b.commit("", cmd, fmt.Sprintf("CMD %v", cmd)); err != nil { 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") 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 { func (b *buildFile) addRemote(container *Container, orig, dest string) error {
file, err := utils.Download(orig, ioutil.Discard) file, err := utils.Download(orig, ioutil.Discard)
if err != nil { if err != nil {

View File

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

View File

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

View File

@ -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) { func grepFile(t *testing.T, path string, pattern string) {
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { if err != nil {

View File

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

View File

@ -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 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. 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 3. Dockerfile Examples
====================== ======================

View File

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