本文整理汇总了Golang中github.com/docker/docker/pkg/stringutils.NewStrSlice函数的典型用法代码示例。如果您正苦于以下问题:Golang NewStrSlice函数的具体用法?Golang NewStrSlice怎么用?Golang NewStrSlice使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了NewStrSlice函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: entrypoint
// ENTRYPOINT /usr/sbin/nginx
//
// Set the entrypoint (which defaults to sh -c on linux, or cmd /S /C on Windows) to
// /usr/sbin/nginx. Will accept the CMD as the arguments to /usr/sbin/nginx.
//
// Handles command processing similar to CMD and RUN, only b.runConfig.Entrypoint
// is initialized at NewBuilder time instead of through argument parsing.
//
func entrypoint(b *Builder, args []string, attributes map[string]bool, original string) error {
if err := b.flags.Parse(); err != nil {
return err
}
parsed := handleJSONArgs(args, attributes)
switch {
case attributes["json"]:
// ENTRYPOINT ["echo", "hi"]
b.runConfig.Entrypoint = stringutils.NewStrSlice(parsed...)
case len(parsed) == 0:
// ENTRYPOINT []
b.runConfig.Entrypoint = nil
default:
// ENTRYPOINT echo hi
if runtime.GOOS != "windows" {
b.runConfig.Entrypoint = stringutils.NewStrSlice("/bin/sh", "-c", parsed[0])
} else {
b.runConfig.Entrypoint = stringutils.NewStrSlice("cmd", "/S", "/C", parsed[0])
}
}
// when setting the entrypoint if a CMD was not explicitly set then
// set the command to nil
if !b.cmdSet {
b.runConfig.Cmd = nil
}
if err := b.commit("", b.runConfig.Cmd, fmt.Sprintf("ENTRYPOINT %q", b.runConfig.Entrypoint)); err != nil {
return err
}
return nil
}
示例2: commit
func (b *Builder) commit(id string, autoCmd *stringutils.StrSlice, comment string) error {
if b.disableCommit {
return nil
}
if b.image == "" && !b.noBaseImage {
return fmt.Errorf("Please provide a source image with `from` prior to commit")
}
b.runConfig.Image = b.image
if id == "" {
cmd := b.runConfig.Cmd
if runtime.GOOS != "windows" {
b.runConfig.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", "#(nop) "+comment)
} else {
b.runConfig.Cmd = stringutils.NewStrSlice("cmd", "/S /C", "REM (nop) "+comment)
}
defer func(cmd *stringutils.StrSlice) { b.runConfig.Cmd = cmd }(cmd)
if hit, err := b.probeCache(); err != nil {
return err
} else if hit {
return nil
}
container, err := b.create()
if err != nil {
return err
}
id = container.ID
if err := container.Mount(); err != nil {
return err
}
defer container.Unmount()
}
container, err := b.docker.Container(id)
if err != nil {
return err
}
// Note: Actually copy the struct
autoConfig := *b.runConfig
autoConfig.Cmd = autoCmd
commitCfg := &daemon.ContainerCommitConfig{
Author: b.maintainer,
Pause: true,
Config: &autoConfig,
}
// Commit the container
image, err := b.docker.Commit(container, commitCfg)
if err != nil {
return err
}
b.docker.Retain(b.id, image.ID)
b.activeImages = append(b.activeImages, image.ID)
b.image = image.ID
return nil
}
示例3: ContainerExecCreate
// ContainerExecCreate sets up an exec in a running container.
func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) {
container, err := d.getActiveContainer(config.Container)
if err != nil {
return "", err
}
cmd := stringutils.NewStrSlice(config.Cmd...)
entrypoint, args := d.getEntrypointAndArgs(stringutils.NewStrSlice(), cmd)
processConfig := &execdriver.ProcessConfig{
CommonProcessConfig: execdriver.CommonProcessConfig{
Tty: config.Tty,
Entrypoint: entrypoint,
Arguments: args,
},
}
setPlatformSpecificExecProcessConfig(config, container, processConfig)
execConfig := exec.NewConfig()
execConfig.OpenStdin = config.AttachStdin
execConfig.OpenStdout = config.AttachStdout
execConfig.OpenStderr = config.AttachStderr
execConfig.ProcessConfig = processConfig
execConfig.ContainerID = container.ID
d.registerExecCommand(container, execConfig)
d.LogContainerEvent(container, "exec_create: "+execConfig.ProcessConfig.Entrypoint+" "+strings.Join(execConfig.ProcessConfig.Arguments, " "))
return execConfig.ID, nil
}
示例4: SendCmdCreate
func (cli Docker) SendCmdCreate(name, image string, entrypoint, cmds []string, userConfig interface{}) ([]byte, int, error) {
config := &runconfig.Config{
Image: image,
Cmd: stringutils.NewStrSlice(cmds...),
}
if len(entrypoint) != 0 {
config.Entrypoint = stringutils.NewStrSlice(entrypoint...)
}
if userConfig != nil {
config = userConfig.(*runconfig.Config)
}
hostConfig := &runconfig.HostConfig{}
containerResp, err := cli.daemon.ContainerCreate(&daemon.ContainerCreateConfig{
Name: name,
Config: config,
HostConfig: hostConfig,
AdjustCPUShares: false,
})
if err != nil {
return nil, 500, err
}
return []byte(containerResp.ID), 200, nil
}
示例5: TestDecodeContainerConfig
func TestDecodeContainerConfig(t *testing.T) {
fixtures := []struct {
file string
entrypoint *stringutils.StrSlice
}{
{"fixtures/container_config_1_14.json", stringutils.NewStrSlice()},
{"fixtures/container_config_1_17.json", stringutils.NewStrSlice("bash")},
{"fixtures/container_config_1_19.json", stringutils.NewStrSlice("bash")},
}
for _, f := range fixtures {
b, err := ioutil.ReadFile(f.file)
if err != nil {
t.Fatal(err)
}
c, h, err := DecodeContainerConfig(bytes.NewReader(b))
if err != nil {
t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err))
}
if c.Image != "ubuntu" {
t.Fatalf("Expected ubuntu image, found %s\n", c.Image)
}
if c.Entrypoint.Len() != f.entrypoint.Len() {
t.Fatalf("Expected %v, found %v\n", f.entrypoint, c.Entrypoint)
}
if h.Memory != 1000 {
t.Fatalf("Expected memory to be 1000, found %d\n", h.Memory)
}
}
}
示例6: ContainerExecCreate
// ContainerExecCreate sets up an exec in a running container.
func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) {
container, err := d.getActiveContainer(config.Container)
if err != nil {
return "", err
}
cmd := stringutils.NewStrSlice(config.Cmd...)
entrypoint, args := d.getEntrypointAndArgs(stringutils.NewStrSlice(), cmd)
processConfig := &execdriver.ProcessConfig{
CommonProcessConfig: execdriver.CommonProcessConfig{
Tty: config.Tty,
Entrypoint: entrypoint,
Arguments: args,
},
}
setPlatformSpecificExecProcessConfig(config, container, processConfig)
ExecConfig := &ExecConfig{
ID: stringid.GenerateNonCryptoID(),
OpenStdin: config.AttachStdin,
OpenStdout: config.AttachStdout,
OpenStderr: config.AttachStderr,
streamConfig: streamConfig{},
ProcessConfig: processConfig,
Container: container,
Running: false,
waitStart: make(chan struct{}),
}
d.registerExecCommand(ExecConfig)
return ExecConfig.ID, nil
}
示例7: cmd
// CMD foo
//
// Set the default command to run in the container (which may be empty).
// Argument handling is the same as RUN.
//
func cmd(b *Builder, args []string, attributes map[string]bool, original string) error {
if err := b.flags.Parse(); err != nil {
return err
}
cmdSlice := handleJSONArgs(args, attributes)
if !attributes["json"] {
if runtime.GOOS != "windows" {
cmdSlice = append([]string{"/bin/sh", "-c"}, cmdSlice...)
} else {
cmdSlice = append([]string{"cmd", "/S", "/C"}, cmdSlice...)
}
}
b.runConfig.Cmd = stringutils.NewStrSlice(cmdSlice...)
if err := b.commit("", b.runConfig.Cmd, fmt.Sprintf("CMD %q", cmdSlice)); err != nil {
return err
}
if len(args) != 0 {
b.cmdSet = true
}
return nil
}
示例8: ContainerExecCreate
// ContainerExecCreate sets up an exec in a running container.
func (d *Daemon) ContainerExecCreate(config *runconfig.ExecConfig) (string, error) {
// Not all drivers support Exec (LXC for example)
if err := checkExecSupport(d.execDriver.Name()); err != nil {
return "", err
}
container, err := d.getActiveContainer(config.Container)
if err != nil {
return "", err
}
cmd := stringutils.NewStrSlice(config.Cmd...)
entrypoint, args := d.getEntrypointAndArgs(stringutils.NewStrSlice(), cmd)
user := config.User
if len(user) == 0 {
user = container.Config.User
}
processConfig := &execdriver.ProcessConfig{
Tty: config.Tty,
Entrypoint: entrypoint,
Arguments: args,
User: user,
Privileged: config.Privileged,
}
ExecConfig := &ExecConfig{
ID: stringid.GenerateNonCryptoID(),
OpenStdin: config.AttachStdin,
OpenStdout: config.AttachStdout,
OpenStderr: config.AttachStderr,
streamConfig: streamConfig{},
ProcessConfig: processConfig,
Container: container,
Running: false,
waitStart: make(chan struct{}),
}
d.registerExecCommand(ExecConfig)
container.logEvent("exec_create: " + ExecConfig.ProcessConfig.Entrypoint + " " + strings.Join(ExecConfig.ProcessConfig.Arguments, " "))
return ExecConfig.ID, nil
}
示例9: TestDecodeContainerConfig
func TestDecodeContainerConfig(t *testing.T) {
var (
fixtures []f
image string
)
if runtime.GOOS != "windows" {
image = "ubuntu"
fixtures = []f{
{"fixtures/unix/container_config_1_14.json", stringutils.NewStrSlice()},
{"fixtures/unix/container_config_1_17.json", stringutils.NewStrSlice("bash")},
{"fixtures/unix/container_config_1_19.json", stringutils.NewStrSlice("bash")},
}
} else {
image = "windows"
fixtures = []f{
{"fixtures/windows/container_config_1_19.json", stringutils.NewStrSlice("cmd")},
}
}
for _, f := range fixtures {
b, err := ioutil.ReadFile(f.file)
if err != nil {
t.Fatal(err)
}
c, h, err := DecodeContainerConfig(bytes.NewReader(b))
if err != nil {
t.Fatal(fmt.Errorf("Error parsing %s: %v", f, err))
}
if c.Image != image {
t.Fatalf("Expected %s image, found %s\n", image, c.Image)
}
if c.Entrypoint.Len() != f.entrypoint.Len() {
t.Fatalf("Expected %v, found %v\n", f.entrypoint, c.Entrypoint)
}
if h != nil && h.Memory != 1000 {
t.Fatalf("Expected memory to be 1000, found %d\n", h.Memory)
}
}
}
示例10: create
func (b *builder) create() (*daemon.Container, error) {
if b.image == "" && !b.noBaseImage {
return nil, fmt.Errorf("Please provide a source image with `from` prior to run")
}
b.Config.Image = b.image
hostConfig := &runconfig.HostConfig{
CPUShares: b.cpuShares,
CPUPeriod: b.cpuPeriod,
CPUQuota: b.cpuQuota,
CpusetCpus: b.cpuSetCpus,
CpusetMems: b.cpuSetMems,
CgroupParent: b.cgroupParent,
Memory: b.memory,
MemorySwap: b.memorySwap,
Ulimits: b.ulimits,
}
config := *b.Config
// Create the container
ccr, err := b.Daemon.ContainerCreate("", b.Config, hostConfig, true)
if err != nil {
return nil, err
}
for _, warning := range ccr.Warnings {
fmt.Fprintf(b.OutStream, " ---> [Warning] %s\n", warning)
}
c, err := b.Daemon.Get(ccr.ID)
if err != nil {
return nil, err
}
b.TmpContainers[c.ID] = struct{}{}
fmt.Fprintf(b.OutStream, " ---> Running in %s\n", stringid.TruncateID(c.ID))
if config.Cmd.Len() > 0 {
// override the entry point that may have been picked up from the base image
s := config.Cmd.Slice()
c.Path = s[0]
c.Args = s[1:]
} else {
config.Cmd = stringutils.NewStrSlice()
}
return c, nil
}
示例11: Parse
//.........这里部分代码省略.........
swappiness := *flSwappiness
if swappiness != -1 && (swappiness < 0 || swappiness > 100) {
return nil, nil, cmd, fmt.Errorf("Invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
}
var parsedShm *int64
if *flShmSize != "" {
shmSize, err := units.RAMInBytes(*flShmSize)
if err != nil {
return nil, nil, cmd, err
}
parsedShm = &shmSize
}
var binds []string
// add any bind targets to the list of container volumes
for bind := range flVolumes.GetMap() {
if arr := volume.SplitN(bind, 2); len(arr) > 1 {
// after creating the bind mount we want to delete it from the flVolumes values because
// we do not want bind mounts being committed to image configs
binds = append(binds, bind)
flVolumes.Delete(bind)
}
}
var (
parsedArgs = cmd.Args()
runCmd *stringutils.StrSlice
entrypoint *stringutils.StrSlice
image = cmd.Arg(0)
)
if len(parsedArgs) > 1 {
runCmd = stringutils.NewStrSlice(parsedArgs[1:]...)
}
if *flEntrypoint != "" {
entrypoint = stringutils.NewStrSlice(*flEntrypoint)
}
var (
domainname string
hostname = *flHostname
parts = strings.SplitN(hostname, ".", 2)
)
if len(parts) > 1 {
hostname = parts[0]
domainname = parts[1]
}
ports, portBindings, err := nat.ParsePortSpecs(flPublish.GetAll())
if err != nil {
return nil, nil, cmd, err
}
// Merge in exposed ports to the map of published ports
for _, e := range flExpose.GetAll() {
if strings.Contains(e, ":") {
return nil, nil, cmd, fmt.Errorf("Invalid port format for --expose: %s", e)
}
//support two formats for expose, original format <portnum>/[<proto>] or <startport-endport>/[<proto>]
proto, port := nat.SplitProtoPort(e)
//parse the start and end port and create a sequence of ports to expose
//if expose a port, the start and end port are the same
start, end, err := parsers.ParsePortRange(port)
if err != nil {
return nil, nil, cmd, fmt.Errorf("Invalid range format for --expose: %s, error: %s", e, err)
示例12: runContextCommand
func (b *builder) runContextCommand(args []string, allowRemote bool, allowDecompression bool, cmdName string) error {
if b.context == nil {
return fmt.Errorf("No context given. Impossible to use %s", cmdName)
}
if len(args) < 2 {
return fmt.Errorf("Invalid %s format - at least two arguments required", cmdName)
}
// Work in daemon-specific filepath semantics
dest := filepath.FromSlash(args[len(args)-1]) // last one is always the dest
copyInfos := []*copyInfo{}
b.Config.Image = b.image
defer func() {
for _, ci := range copyInfos {
if ci.tmpDir != "" {
os.RemoveAll(ci.tmpDir)
}
}
}()
// Loop through each src file and calculate the info we need to
// do the copy (e.g. hash value if cached). Don't actually do
// the copy until we've looked at all src files
for _, orig := range args[0 : len(args)-1] {
if err := calcCopyInfo(
b,
cmdName,
©Infos,
orig,
dest,
allowRemote,
allowDecompression,
true,
); err != nil {
return err
}
}
if len(copyInfos) == 0 {
return fmt.Errorf("No source files were specified")
}
if len(copyInfos) > 1 && !strings.HasSuffix(dest, string(os.PathSeparator)) {
return fmt.Errorf("When using %s with more than one source file, the destination must be a directory and end with a /", cmdName)
}
// For backwards compat, if there's just one CI then use it as the
// cache look-up string, otherwise hash 'em all into one
var srcHash string
var origPaths string
if len(copyInfos) == 1 {
srcHash = copyInfos[0].hash
origPaths = copyInfos[0].origPath
} else {
var hashs []string
var origs []string
for _, ci := range copyInfos {
hashs = append(hashs, ci.hash)
origs = append(origs, ci.origPath)
}
hasher := sha256.New()
hasher.Write([]byte(strings.Join(hashs, ",")))
srcHash = "multi:" + hex.EncodeToString(hasher.Sum(nil))
origPaths = strings.Join(origs, " ")
}
cmd := b.Config.Cmd
if runtime.GOOS != "windows" {
b.Config.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest))
} else {
b.Config.Cmd = stringutils.NewStrSlice("cmd", "/S /C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest))
}
defer func(cmd *stringutils.StrSlice) { b.Config.Cmd = cmd }(cmd)
hit, err := b.probeCache()
if err != nil {
return err
}
if hit {
return nil
}
container, _, err := b.Daemon.ContainerCreate("", b.Config, nil, true)
if err != nil {
return err
}
b.TmpContainers[container.ID] = struct{}{}
if err := container.Mount(); err != nil {
return err
}
defer container.Unmount()
for _, ci := range copyInfos {
if err := b.addContext(container, ci.origPath, ci.destPath, ci.decompress); err != nil {
//.........这里部分代码省略.........
示例13: runContextCommand
func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalDecompression bool, cmdName string) error {
if b.context == nil {
return fmt.Errorf("No context given. Impossible to use %s", cmdName)
}
if len(args) < 2 {
return fmt.Errorf("Invalid %s format - at least two arguments required", cmdName)
}
// Work in daemon-specific filepath semantics
dest := filepath.FromSlash(args[len(args)-1]) // last one is always the dest
b.runConfig.Image = b.image
var infos []copyInfo
// Loop through each src file and calculate the info we need to
// do the copy (e.g. hash value if cached). Don't actually do
// the copy until we've looked at all src files
var err error
for _, orig := range args[0 : len(args)-1] {
var fi builder.FileInfo
decompress := allowLocalDecompression
if urlutil.IsURL(orig) {
if !allowRemote {
return fmt.Errorf("Source can't be a URL for %s", cmdName)
}
fi, err = b.download(orig)
if err != nil {
return err
}
defer os.RemoveAll(filepath.Dir(fi.Path()))
decompress = false
infos = append(infos, copyInfo{fi, decompress})
continue
}
// not a URL
subInfos, err := b.calcCopyInfo(cmdName, orig, allowLocalDecompression, true)
if err != nil {
return err
}
infos = append(infos, subInfos...)
}
if len(infos) == 0 {
return fmt.Errorf("No source files were specified")
}
if len(infos) > 1 && !strings.HasSuffix(dest, string(os.PathSeparator)) {
return fmt.Errorf("When using %s with more than one source file, the destination must be a directory and end with a /", cmdName)
}
// For backwards compat, if there's just one info then use it as the
// cache look-up string, otherwise hash 'em all into one
var srcHash string
var origPaths string
if len(infos) == 1 {
fi := infos[0].FileInfo
origPaths = fi.Name()
if hfi, ok := fi.(builder.Hashed); ok {
srcHash = hfi.Hash()
}
} else {
var hashs []string
var origs []string
for _, info := range infos {
fi := info.FileInfo
origs = append(origs, fi.Name())
if hfi, ok := fi.(builder.Hashed); ok {
hashs = append(hashs, hfi.Hash())
}
}
hasher := sha256.New()
hasher.Write([]byte(strings.Join(hashs, ",")))
srcHash = "multi:" + hex.EncodeToString(hasher.Sum(nil))
origPaths = strings.Join(origs, " ")
}
cmd := b.runConfig.Cmd
if runtime.GOOS != "windows" {
b.runConfig.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest))
} else {
b.runConfig.Cmd = stringutils.NewStrSlice("cmd", "/S", "/C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest))
}
defer func(cmd *stringutils.StrSlice) { b.runConfig.Cmd = cmd }(cmd)
if hit, err := b.probeCache(); err != nil {
return err
} else if hit {
return nil
}
// Create the Pod
podId := fmt.Sprintf("buildpod-%s", utils.RandStr(10, "alpha"))
tempSrcDir := fmt.Sprintf("/var/run/hyper/temp/%s/", podId)
if err := os.MkdirAll(tempSrcDir, 0755); err != nil {
glog.Errorf(err.Error())
return err
}
//.........这里部分代码省略.........
示例14: runContextCommand
func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalDecompression bool, cmdName string) error {
if b.context == nil {
return fmt.Errorf("No context given. Impossible to use %s", cmdName)
}
if len(args) < 2 {
return fmt.Errorf("Invalid %s format - at least two arguments required", cmdName)
}
// Work in daemon-specific filepath semantics
dest := filepath.FromSlash(args[len(args)-1]) // last one is always the dest
b.runConfig.Image = b.image
var infos []copyInfo
// Loop through each src file and calculate the info we need to
// do the copy (e.g. hash value if cached). Don't actually do
// the copy until we've looked at all src files
var err error
for _, orig := range args[0 : len(args)-1] {
var fi builder.FileInfo
decompress := allowLocalDecompression
if urlutil.IsURL(orig) {
if !allowRemote {
return fmt.Errorf("Source can't be a URL for %s", cmdName)
}
fi, err = b.download(orig)
if err != nil {
return err
}
defer os.RemoveAll(filepath.Dir(fi.Path()))
decompress = false
infos = append(infos, copyInfo{fi, decompress})
continue
}
// not a URL
subInfos, err := b.calcCopyInfo(cmdName, orig, allowLocalDecompression, true)
if err != nil {
return err
}
infos = append(infos, subInfos...)
}
if len(infos) == 0 {
return fmt.Errorf("No source files were specified")
}
if len(infos) > 1 && !strings.HasSuffix(dest, string(os.PathSeparator)) {
return fmt.Errorf("When using %s with more than one source file, the destination must be a directory and end with a /", cmdName)
}
// For backwards compat, if there's just one info then use it as the
// cache look-up string, otherwise hash 'em all into one
var srcHash string
var origPaths string
if len(infos) == 1 {
fi := infos[0].FileInfo
origPaths = fi.Name()
if hfi, ok := fi.(builder.Hashed); ok {
srcHash = hfi.Hash()
}
} else {
var hashs []string
var origs []string
for _, info := range infos {
fi := info.FileInfo
origs = append(origs, fi.Name())
if hfi, ok := fi.(builder.Hashed); ok {
hashs = append(hashs, hfi.Hash())
}
}
hasher := sha256.New()
hasher.Write([]byte(strings.Join(hashs, ",")))
srcHash = "multi:" + hex.EncodeToString(hasher.Sum(nil))
origPaths = strings.Join(origs, " ")
}
cmd := b.runConfig.Cmd
if runtime.GOOS != "windows" {
b.runConfig.Cmd = stringutils.NewStrSlice("/bin/sh", "-c", fmt.Sprintf("#(nop) %s %s in %s", cmdName, srcHash, dest))
} else {
b.runConfig.Cmd = stringutils.NewStrSlice("cmd", "/S /C", fmt.Sprintf("REM (nop) %s %s in %s", cmdName, srcHash, dest))
}
defer func(cmd *stringutils.StrSlice) { b.runConfig.Cmd = cmd }(cmd)
if hit, err := b.probeCache(); err != nil {
return err
} else if hit {
return nil
}
container, _, err := b.docker.Create(b.runConfig, nil)
if err != nil {
return err
}
defer container.Unmount()
b.tmpContainers[container.ID] = struct{}{}
//.........这里部分代码省略.........
示例15: run
// RUN some command yo
//
// run a command and commit the image. Args are automatically prepended with
// 'sh -c' under linux or 'cmd /S /C' under Windows, in the event there is
// only one argument. The difference in processing:
//
// RUN echo hi # sh -c echo hi (Linux)
// RUN echo hi # cmd /S /C echo hi (Windows)
// RUN [ "echo", "hi" ] # echo hi
//
func run(b *Builder, args []string, attributes map[string]bool, original string) error {
if b.image == "" && !b.noBaseImage {
return derr.ErrorCodeMissingFrom
}
if err := b.flags.Parse(); err != nil {
return err
}
args = handleJSONArgs(args, attributes)
if !attributes["json"] {
if runtime.GOOS != "windows" {
args = append([]string{"/bin/sh", "-c"}, args...)
} else {
args = append([]string{"cmd", "/S", "/C"}, args...)
}
}
runCmd := flag.NewFlagSet("run", flag.ContinueOnError)
runCmd.SetOutput(ioutil.Discard)
runCmd.Usage = nil
config, _, _, err := runconfig.Parse(runCmd, append([]string{b.image}, args...))
if err != nil {
return err
}
// stash the cmd
cmd := b.runConfig.Cmd
runconfig.Merge(b.runConfig, config)
// stash the config environment
env := b.runConfig.Env
defer func(cmd *stringutils.StrSlice) { b.runConfig.Cmd = cmd }(cmd)
defer func(env []string) { b.runConfig.Env = env }(env)
// derive the net build-time environment for this run. We let config
// environment override the build time environment.
// This means that we take the b.buildArgs list of env vars and remove
// any of those variables that are defined as part of the container. In other
// words, anything in b.Config.Env. What's left is the list of build-time env
// vars that we need to add to each RUN command - note the list could be empty.
//
// We don't persist the build time environment with container's config
// environment, but just sort and prepend it to the command string at time
// of commit.
// This helps with tracing back the image's actual environment at the time
// of RUN, without leaking it to the final image. It also aids cache
// lookup for same image built with same build time environment.
cmdBuildEnv := []string{}
configEnv := runconfig.ConvertKVStringsToMap(b.runConfig.Env)
for key, val := range b.BuildArgs {
if !b.isBuildArgAllowed(key) {
// skip build-args that are not in allowed list, meaning they have
// not been defined by an "ARG" Dockerfile command yet.
// This is an error condition but only if there is no "ARG" in the entire
// Dockerfile, so we'll generate any necessary errors after we parsed
// the entire file (see 'leftoverArgs' processing in evaluator.go )
continue
}
if _, ok := configEnv[key]; !ok {
cmdBuildEnv = append(cmdBuildEnv, fmt.Sprintf("%s=%s", key, val))
}
}
// derive the command to use for probeCache() and to commit in this container.
// Note that we only do this if there are any build-time env vars. Also, we
// use the special argument "|#" at the start of the args array. This will
// avoid conflicts with any RUN command since commands can not
// start with | (vertical bar). The "#" (number of build envs) is there to
// help ensure proper cache matches. We don't want a RUN command
// that starts with "foo=abc" to be considered part of a build-time env var.
saveCmd := config.Cmd
if len(cmdBuildEnv) > 0 {
sort.Strings(cmdBuildEnv)
tmpEnv := append([]string{fmt.Sprintf("|%d", len(cmdBuildEnv))}, cmdBuildEnv...)
saveCmd = stringutils.NewStrSlice(append(tmpEnv, saveCmd.Slice()...)...)
}
b.runConfig.Cmd = saveCmd
hit, err := b.probeCache()
if err != nil {
return err
}
if hit {
return nil
}
// set Cmd manually, this is special case only for Dockerfiles
//.........这里部分代码省略.........