func (b *buildFile) addContext(container *Container, orig, dest string) error { var ( origPath = path.Join(b.contextPath, orig) destPath = path.Join(container.BasefsPath(), dest) ) // Preserve the trailing '/' if strings.HasSuffix(dest, "/") { destPath = destPath + "/" } 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() { if err := archive.CopyWithTar(origPath, destPath); err != nil { return err } // First try to unpack the source as an archive } else if err := archive.UntarPath(origPath, destPath); err != nil { utils.Debugf("Couldn't untar %s to %s: %s", origPath, destPath, err) // If that fails, just copy it as a regular file if err := os.MkdirAll(path.Dir(destPath), 0755); err != nil { return err } if err := archive.CopyWithTar(origPath, destPath); err != nil { return err } } return nil }
func (container *Container) createVolumes() error { binds, err := container.getBindMap() if err != nil { return err } volumesDriver := container.runtime.volumes.driver // Create the requested volumes if they don't exist for volPath := range container.Config.Volumes { volPath = path.Clean(volPath) volIsDir := true // Skip existing volumes if _, exists := container.Volumes[volPath]; exists { continue } var srcPath string var isBindMount bool srcRW := false // If an external bind is defined for this volume, use that as a source if bindMap, exists := binds[volPath]; exists { isBindMount = true srcPath = bindMap.SrcPath if strings.ToLower(bindMap.Mode) == "rw" { srcRW = true } if stat, err := os.Stat(bindMap.SrcPath); err != nil { return err } else { volIsDir = stat.IsDir() } // Otherwise create an directory in $ROOT/volumes/ and use that } else { // Do not pass a container as the parameter for the volume creation. // The graph driver using the container's information ( Image ) to // create the parent. c, err := container.runtime.volumes.Create(nil, nil, "", "", nil) if err != nil { return err } srcPath, err = volumesDriver.Get(c.ID) if err != nil { return fmt.Errorf("Driver %s failed to get volume rootfs %s: %s", volumesDriver, c.ID, err) } srcRW = true // RW by default } if p, err := filepath.EvalSymlinks(srcPath); err != nil { return err } else { srcPath = p } container.Volumes[volPath] = srcPath container.VolumesRW[volPath] = srcRW // Create the mountpoint volPath = path.Join(container.basefs, volPath) rootVolPath, err := utils.FollowSymlinkInScope(volPath, container.basefs) if err != nil { return err } if _, err := os.Stat(rootVolPath); err != nil { if os.IsNotExist(err) { if volIsDir { if err := os.MkdirAll(rootVolPath, 0755); err != nil { return err } } else { if err := os.MkdirAll(path.Dir(rootVolPath), 0755); err != nil { return err } if f, err := os.OpenFile(rootVolPath, os.O_CREATE, 0755); err != nil { return err } else { f.Close() } } } } // Do not copy or change permissions if we are mounting from the host if srcRW && !isBindMount { volList, err := ioutil.ReadDir(rootVolPath) if err != nil { return err } if len(volList) > 0 { srcList, err := ioutil.ReadDir(srcPath) if err != nil { return err } if len(srcList) == 0 { // If the source volume is empty copy files from the root into the volume if err := archive.CopyWithTar(rootVolPath, srcPath); err != nil { return err } var stat syscall.Stat_t if err := syscall.Stat(rootVolPath, &stat); err != nil { return err } var srcStat syscall.Stat_t if err := syscall.Stat(srcPath, &srcStat); err != nil { return err } // Change the source volume's ownership if it differs from the root // files that were just copied if stat.Uid != srcStat.Uid || stat.Gid != srcStat.Gid { if err := os.Chown(srcPath, int(stat.Uid), int(stat.Gid)); err != nil { return err } } } } } } return nil }