github.com/baris/docker@v1.7.0/daemon/create.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"github.com/docker/docker/graph"
    10  	"github.com/docker/docker/image"
    11  	"github.com/docker/docker/pkg/parsers"
    12  	"github.com/docker/docker/pkg/stringid"
    13  	"github.com/docker/docker/runconfig"
    14  	"github.com/docker/libcontainer/label"
    15  )
    16  
    17  func (daemon *Daemon) ContainerCreate(name string, config *runconfig.Config, hostConfig *runconfig.HostConfig) (string, []string, error) {
    18  	if config == nil {
    19  		return "", nil, fmt.Errorf("Config cannot be empty in order to create a container")
    20  	}
    21  
    22  	warnings, err := daemon.verifyHostConfig(hostConfig)
    23  	if err != nil {
    24  		return "", warnings, err
    25  	}
    26  
    27  	// The check for a valid workdir path is made on the server rather than in the
    28  	// client. This is because we don't know the type of path (Linux or Windows)
    29  	// to validate on the client.
    30  	if config.WorkingDir != "" && !filepath.IsAbs(config.WorkingDir) {
    31  		return "", warnings, fmt.Errorf("The working directory '%s' is invalid. It needs to be an absolute path.", config.WorkingDir)
    32  	}
    33  
    34  	container, buildWarnings, err := daemon.Create(config, hostConfig, name)
    35  	if err != nil {
    36  		if daemon.Graph().IsNotExist(err, config.Image) {
    37  			_, tag := parsers.ParseRepositoryTag(config.Image)
    38  			if tag == "" {
    39  				tag = graph.DEFAULTTAG
    40  			}
    41  			return "", warnings, fmt.Errorf("No such image: %s (tag: %s)", config.Image, tag)
    42  		}
    43  		return "", warnings, err
    44  	}
    45  
    46  	container.LogEvent("create")
    47  	warnings = append(warnings, buildWarnings...)
    48  
    49  	return container.ID, warnings, nil
    50  }
    51  
    52  // Create creates a new container from the given configuration with a given name.
    53  func (daemon *Daemon) Create(config *runconfig.Config, hostConfig *runconfig.HostConfig, name string) (*Container, []string, error) {
    54  	var (
    55  		container *Container
    56  		warnings  []string
    57  		img       *image.Image
    58  		imgID     string
    59  		err       error
    60  	)
    61  
    62  	if config.Image != "" {
    63  		img, err = daemon.repositories.LookupImage(config.Image)
    64  		if err != nil {
    65  			return nil, nil, err
    66  		}
    67  		if err = img.CheckDepth(); err != nil {
    68  			return nil, nil, err
    69  		}
    70  		imgID = img.ID
    71  	}
    72  
    73  	if warnings, err = daemon.mergeAndVerifyConfig(config, img); err != nil {
    74  		return nil, nil, err
    75  	}
    76  	if !config.NetworkDisabled && daemon.SystemConfig().IPv4ForwardingDisabled {
    77  		warnings = append(warnings, "IPv4 forwarding is disabled.\n")
    78  	}
    79  	if hostConfig == nil {
    80  		hostConfig = &runconfig.HostConfig{}
    81  	}
    82  	if hostConfig.SecurityOpt == nil {
    83  		hostConfig.SecurityOpt, err = daemon.GenerateSecurityOpt(hostConfig.IpcMode, hostConfig.PidMode)
    84  		if err != nil {
    85  			return nil, nil, err
    86  		}
    87  	}
    88  	if container, err = daemon.newContainer(name, config, imgID); err != nil {
    89  		return nil, nil, err
    90  	}
    91  	if err := daemon.Register(container); err != nil {
    92  		return nil, nil, err
    93  	}
    94  	if err := daemon.createRootfs(container); err != nil {
    95  		return nil, nil, err
    96  	}
    97  	if err := daemon.setHostConfig(container, hostConfig); err != nil {
    98  		return nil, nil, err
    99  	}
   100  	if err := container.Mount(); err != nil {
   101  		return nil, nil, err
   102  	}
   103  	defer container.Unmount()
   104  
   105  	for spec := range config.Volumes {
   106  		var (
   107  			name, destination string
   108  			parts             = strings.Split(spec, ":")
   109  		)
   110  		switch len(parts) {
   111  		case 2:
   112  			name, destination = parts[0], filepath.Clean(parts[1])
   113  		default:
   114  			name = stringid.GenerateRandomID()
   115  			destination = filepath.Clean(parts[0])
   116  		}
   117  		// Skip volumes for which we already have something mounted on that
   118  		// destination because of a --volume-from.
   119  		if container.isDestinationMounted(destination) {
   120  			continue
   121  		}
   122  		path, err := container.GetResourcePath(destination)
   123  		if err != nil {
   124  			return nil, nil, err
   125  		}
   126  
   127  		stat, err := os.Stat(path)
   128  		if err == nil && !stat.IsDir() {
   129  			return nil, nil, fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
   130  		}
   131  
   132  		v, err := createVolume(name, config.VolumeDriver)
   133  		if err != nil {
   134  			return nil, nil, err
   135  		}
   136  		if err := label.Relabel(v.Path(), container.MountLabel, "z"); err != nil {
   137  			return nil, nil, err
   138  		}
   139  
   140  		if err := container.copyImagePathContent(v, destination); err != nil {
   141  			return nil, nil, err
   142  		}
   143  
   144  		container.addMountPointWithVolume(destination, v, true)
   145  	}
   146  	if err := container.ToDisk(); err != nil {
   147  		return nil, nil, err
   148  	}
   149  	return container, warnings, nil
   150  }
   151  
   152  func (daemon *Daemon) GenerateSecurityOpt(ipcMode runconfig.IpcMode, pidMode runconfig.PidMode) ([]string, error) {
   153  	if ipcMode.IsHost() || pidMode.IsHost() {
   154  		return label.DisableSecOpt(), nil
   155  	}
   156  	if ipcContainer := ipcMode.Container(); ipcContainer != "" {
   157  		c, err := daemon.Get(ipcContainer)
   158  		if err != nil {
   159  			return nil, err
   160  		}
   161  
   162  		return label.DupSecOpt(c.ProcessLabel), nil
   163  	}
   164  	return nil, nil
   165  }