func (b *Builder) run(c *daemon.Container) error { var errCh chan error if b.Verbose { errCh = b.Daemon.Attach(&c.StreamConfig, c.Config.OpenStdin, c.Config.StdinOnce, c.Config.Tty, nil, b.OutStream, b.ErrStream) } //start the container if err := c.Start(); err != nil { return err } if err := <-errCh; err != nil { return err } // Wait for it to finish if ret, _ := c.WaitStop(-1 * time.Second); ret != 0 { err := &utils.JSONError{ Message: fmt.Sprintf("The command %v returned a non-zero code: %d", b.Config.Cmd, ret), Code: ret, } return err } return nil }
func unsetRaw(t *testing.T, c *daemon.Container, state *term.State) { pty, err := c.GetPtyMaster() if err != nil { t.Fatal(err) } term.RestoreTerminal(pty.Fd(), state) }
func (b *buildFile) run(c *daemon.Container) error { var errCh chan error if b.verbose { errCh = utils.Go(func() error { return <-b.daemon.Attach(c, nil, nil, b.outStream, b.errStream) }) } //start the container if err := c.Start(); err != nil { return err } if errCh != nil { if err := <-errCh; err != nil { return err } } // Wait for it to finish if ret, _ := c.State.WaitStop(-1 * time.Second); ret != 0 { err := &utils.JSONError{ Message: fmt.Sprintf("The command %v returned a non-zero code: %d", b.config.Cmd, ret), Code: ret, } return err } return nil }
func (b *Builder) run(c *daemon.Container) error { //start the container if err := c.Start(); err != nil { return err } if b.Verbose { logsJob := b.Engine.Job("logs", c.ID) logsJob.Setenv("follow", "1") logsJob.Setenv("stdout", "1") logsJob.Setenv("stderr", "1") logsJob.Stdout.Add(b.OutStream) logsJob.Stderr.Set(b.ErrStream) if err := logsJob.Run(); err != nil { return err } } // Wait for it to finish if ret, _ := c.WaitStop(-1 * time.Second); ret != 0 { err := &utils.JSONError{ Message: fmt.Sprintf("The command %v returned a non-zero code: %d", b.Config.Cmd, ret), Code: ret, } return err } return nil }
func (b *buildFile) run(c *daemon.Container) error { var errCh chan error if b.verbose { errCh = utils.Go(func() error { // FIXME: call the 'attach' job so that daemon.Attach can be made private // // FIXME (LK4D4): Also, maybe makes sense to call "logs" job, it is like attach // but without hijacking for stdin. Also, with attach there can be race // condition because of some output already was printed before it. return <-b.daemon.Attach(c, nil, nil, b.outStream, b.errStream) }) } //start the container if err := c.Start(); err != nil { return err } if errCh != nil { if err := <-errCh; err != nil { return err } } // Wait for it to finish if ret, _ := c.State.WaitStop(-1 * time.Second); ret != 0 { err := &utils.JSONError{ Message: fmt.Sprintf("The command %v returned a non-zero code: %d", b.config.Cmd, ret), Code: ret, } return err } return nil }
func (srv *Server) setHostConfig(container *daemon.Container, hostConfig *runconfig.HostConfig) error { // Validate the HostConfig binds. Make sure that: // the source exists for _, bind := range hostConfig.Binds { splitBind := strings.Split(bind, ":") source := splitBind[0] // ensure the source exists on the host _, err := os.Stat(source) if err != nil && os.IsNotExist(err) { err = os.MkdirAll(source, 0755) if err != nil { return fmt.Errorf("Could not create local directory '%s' for bind mount: %s!", source, err.Error()) } } } // Register any links from the host config before starting the container if err := srv.daemon.RegisterLinks(container, hostConfig); err != nil { return err } container.SetHostConfig(hostConfig) container.ToDisk() return nil }
// Commit will create a new image from a container's changes // TODO: remove daemon, make Commit a method on *Builder ? func Commit(container *daemon.Container, d *daemon.Daemon, c *CommitConfig) (string, error) { // It is not possible to commit a running container on Windows if runtime.GOOS == "windows" && container.IsRunning() { return "", fmt.Errorf("Windows does not support commit of a running container") } if c.Config == nil { c.Config = &runconfig.Config{} } newConfig, err := BuildFromConfig(c.Config, c.Changes) if err != nil { return "", err } if err := runconfig.Merge(newConfig, container.Config); err != nil { return "", err } commitCfg := &daemon.ContainerCommitConfig{ Pause: c.Pause, Repo: c.Repo, Tag: c.Tag, Author: c.Author, Comment: c.Comment, Config: newConfig, } img, err := d.Commit(container, commitCfg) if err != nil { return "", err } return img.ID, nil }
func setRaw(t *testing.T, c *daemon.Container) *term.State { pty, err := c.GetPtyMaster() if err != nil { t.Fatal(err) } state, err := term.MakeRaw(pty.Fd()) if err != nil { t.Fatal(err) } return state }
func (b *Builder) run(c *daemon.Container) error { var errCh chan error if b.Verbose { errCh = c.Attach(nil, b.Stdout, b.Stderr) } //start the container if err := b.docker.Start(c); err != nil { return err } finished := make(chan struct{}) defer close(finished) go func() { select { case <-b.cancelled: logrus.Debugln("Build cancelled, killing and removing container:", c.ID) b.docker.Kill(c) b.removeContainer(c.ID) case <-finished: } }() if b.Verbose { // Block on reading output from container, stop on err or chan closed if err := <-errCh; err != nil { return err } } // Wait for it to finish if ret, _ := c.WaitStop(-1 * time.Second); ret != 0 { // TODO: change error type, because jsonmessage.JSONError assumes HTTP return &jsonmessage.JSONError{ Message: fmt.Sprintf("The command '%s' returned a non-zero code: %d", b.runConfig.Cmd.ToString(), ret), Code: ret, } } return nil }
func (b *Builder) run(c *daemon.Container) error { var errCh chan error if b.Verbose { errCh = c.Attach(nil, b.OutStream, b.ErrStream) } //start the container if err := c.Start(); err != nil { return err } finished := make(chan struct{}) defer close(finished) go func() { select { case <-b.cancelled: logrus.Debugln("Build cancelled, killing container:", c.ID) c.Kill() case <-finished: } }() if b.Verbose { // Block on reading output from container, stop on err or chan closed if err := <-errCh; err != nil { return err } } // Wait for it to finish if ret, _ := c.WaitStop(-1 * time.Second); ret != 0 { err := &jsonmessage.JSONError{ Message: fmt.Sprintf("The command %v returned a non-zero code: %d", b.Config.Cmd, ret), Code: ret, } return err } return nil }
func (b *Builder) addContext(container *daemon.Container, orig, dest string, decompress bool) error { var ( err error destExists = true origPath = path.Join(b.contextPath, orig) destPath = path.Join(container.RootfsPath(), dest) ) if destPath != container.RootfsPath() { destPath, err = symlink.FollowSymlinkInScope(destPath, container.RootfsPath()) if err != nil { return err } } // Preserve the trailing '/' if strings.HasSuffix(dest, "/") || dest == "." { destPath = destPath + "/" } destStat, err := os.Stat(destPath) if err != nil { if !os.IsNotExist(err) { return err } destExists = false } fi, err := os.Stat(origPath) if err != nil { if os.IsNotExist(err) { return fmt.Errorf("%s: no such file or directory", orig) } return err } if fi.IsDir() { return copyAsDirectory(origPath, destPath, destExists) } // If we are adding a remote file (or we've been told not to decompress), do not try to untar it if decompress { // First try to unpack the source as an archive // to support the untar feature we need to clean up the path a little bit // because tar is very forgiving. First we need to strip off the archive's // filename from the path but this is only added if it does not end in / . tarDest := destPath if strings.HasSuffix(tarDest, "/") { tarDest = filepath.Dir(destPath) } // try to successfully untar the orig if err := chrootarchive.UntarPath(origPath, tarDest); err == nil { return nil } else if err != io.EOF { log.Debugf("Couldn't untar %s to %s: %s", origPath, tarDest, err) } } if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil { return err } if err := chrootarchive.CopyWithTar(origPath, destPath); err != nil { return err } resPath := destPath if destExists && destStat.IsDir() { resPath = path.Join(destPath, path.Base(origPath)) } return fixPermissions(origPath, resPath, 0, 0, destExists) }
func (b *builder) addContext(container *daemon.Container, orig, dest string, decompress bool) error { var ( err error destExists = true origPath = filepath.Join(b.contextPath, orig) destPath string ) // Work in daemon-local OS specific file paths dest = filepath.FromSlash(dest) destPath, err = container.GetResourcePath(dest) if err != nil { return err } // Preserve the trailing slash if strings.HasSuffix(dest, string(os.PathSeparator)) || dest == "." { destPath = destPath + string(os.PathSeparator) } destStat, err := os.Stat(destPath) if err != nil { if !os.IsNotExist(err) { logrus.Errorf("Error performing os.Stat on %s. %s", destPath, err) return err } destExists = false } fi, err := os.Stat(origPath) if err != nil { if os.IsNotExist(err) { return fmt.Errorf("%s: no such file or directory", orig) } return err } if fi.IsDir() { return copyAsDirectory(origPath, destPath, destExists) } // If we are adding a remote file (or we've been told not to decompress), do not try to untar it if decompress { // First try to unpack the source as an archive // to support the untar feature we need to clean up the path a little bit // because tar is very forgiving. First we need to strip off the archive's // filename from the path but this is only added if it does not end in slash tarDest := destPath if strings.HasSuffix(tarDest, string(os.PathSeparator)) { tarDest = filepath.Dir(destPath) } // try to successfully untar the orig if err := chrootarchive.UntarPath(origPath, tarDest); err == nil { return nil } else if err != io.EOF { logrus.Debugf("Couldn't untar %s to %s: %s", origPath, tarDest, err) } } if err := system.MkdirAll(filepath.Dir(destPath), 0755); err != nil { return err } if err := chrootarchive.CopyWithTar(origPath, destPath); err != nil { return err } resPath := destPath if destExists && destStat.IsDir() { resPath = filepath.Join(destPath, filepath.Base(origPath)) } return fixPermissions(origPath, resPath, 0, 0, destExists) }
// Copy copies/extracts a source FileInfo to a destination path inside a container // specified by a container object. // TODO: make sure callers don't unnecessarily convert destPath with filepath.FromSlash (Copy does it already). // Copy should take in abstract paths (with slashes) and the implementation should convert it to OS-specific paths. func (d Docker) Copy(c *daemon.Container, destPath string, src builder.FileInfo, decompress bool) error { srcPath := src.Path() destExists := true rootUID, rootGID := d.Daemon.GetRemappedUIDGID() // Work in daemon-local OS specific file paths destPath = filepath.FromSlash(destPath) dest, err := c.GetResourcePath(destPath) if err != nil { return err } // Preserve the trailing slash // TODO: why are we appending another path separator if there was already one? if strings.HasSuffix(destPath, string(os.PathSeparator)) || destPath == "." { dest += string(os.PathSeparator) } destPath = dest destStat, err := os.Stat(destPath) if err != nil { if !os.IsNotExist(err) { logrus.Errorf("Error performing os.Stat on %s. %s", destPath, err) return err } destExists = false } if src.IsDir() { // copy as directory if err := d.Archiver.CopyWithTar(srcPath, destPath); err != nil { return err } return fixPermissions(srcPath, destPath, rootUID, rootGID, destExists) } if decompress { // Only try to untar if it is a file and that we've been told to decompress (when ADD-ing a remote file) // First try to unpack the source as an archive // to support the untar feature we need to clean up the path a little bit // because tar is very forgiving. First we need to strip off the archive's // filename from the path but this is only added if it does not end in slash tarDest := destPath if strings.HasSuffix(tarDest, string(os.PathSeparator)) { tarDest = filepath.Dir(destPath) } // try to successfully untar the orig if err := d.Archiver.UntarPath(srcPath, tarDest); err == nil { return nil } else if err != io.EOF { logrus.Debugf("Couldn't untar to %s: %v", tarDest, err) } } // only needed for fixPermissions, but might as well put it before CopyFileWithTar if destExists && destStat.IsDir() { destPath = filepath.Join(destPath, filepath.Base(srcPath)) } if err := idtools.MkdirAllNewAs(filepath.Dir(destPath), 0755, rootUID, rootGID); err != nil { return err } if err := d.Archiver.CopyFileWithTar(srcPath, destPath); err != nil { return err } return fixPermissions(srcPath, destPath, rootUID, rootGID, destExists) }