Beispiel #1
0
func ContainerCreate(r *TagStore, config *Config) (*Container, error) {
	if config.Memory != 0 && config.Memory < 524288 {
		return nil, fmt.Errorf("Memory limit must be given in bytes (minimum 524288 bytes)")
	}

	var err error
	var img *Image

	if config.Image == "" {
		img = &Image{}
	} else {
		// Lookup image
		img, err = r.LookupImage(config.Image)
		if err != nil {
			return nil, err
		}

		if img.Config != nil {
			MergeConfig(config, img.Config)
		}
	}

	if len(config.Entrypoint) != 0 && config.Cmd == nil {
		config.Cmd = []string{}
	} else if config.Cmd == nil || len(config.Cmd) == 0 {
		return nil, fmt.Errorf("No command specified")
	}

	// Generate id
	id := utils.GenerateID()

	// Generate default hostname
	// FIXME: the lxc template no longer needs to set a default hostname
	if config.Hostname == "" {
		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{
		ID:              id,
		Created:         time.Now(),
		Path:            entrypoint,
		Args:            args, //FIXME: de-duplicate from config
		Config:          config,
		Image:           img.ID, // Always use the resolved image id
		imageO:          img,
		NetworkSettings: &NetworkSettings{},
		// FIXME: do we need to store this in the container?
		SysInitPath: sysInitPath,
	}

	container.root = path.Join(DIR, "containers", container.ID)

	// Step 1: create the container directory.
	// This doubles as a barrier to avoid race conditions.
	if err := os.Mkdir(container.root, 0700); err != nil {
		return nil, err
	}

	// resolvConf, err := GetResolvConf()
	// if err != nil {
	// return nil, err
	// }

	// If custom dns exists, then create a resolv.conf for the container
	if len(config.Dns) > 0 {
		var dns []string
		if len(config.Dns) > 0 {
			dns = config.Dns
		}

		container.ResolvConfPath = path.Join(container.root, "resolv.conf")

		f, err := os.Create(container.ResolvConfPath)
		if err != nil {
			return nil, err
		}
		defer f.Close()
		for _, dns := range dns {
			if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
				return nil, err
			}
		}
	} else {
		container.ResolvConfPath = "/etc/resolv.conf"
	}

	// Step 2: save the container json
	if err := container.ToDisk(); err != nil {
		return nil, err
	}

	return container, nil
}
Beispiel #2
0
func (container *Container) Commit(comment, author string, config *Config, squash bool, fast bool) (*Image, error) {

	if config == nil {
		config = container.Config
	} else {
		MergeConfig(config, container.Config)
	}

	img := &Image{
		ID:              utils.GenerateID(),
		Parent:          container.Image,
		Comment:         comment,
		Created:         time.Now(),
		ContainerConfig: *container.Config,
		Author:          author,
		Config:          config,
		Architecture:    "x86_64",
	}

	logv("Creating image %s", utils.TruncateID(img.ID))

	root := path.Join(DIR, "graph", "_armktmp-"+img.ID)

	os.MkdirAll(root, 0755)

	layerPath := path.Join(root, "layer")

	if squash {
		layerFs := path.Join(root, "layer.fs")

		logv("Generating squashfs...")

		utils.Run("mksquashfs", container.rwPath(), layerFs, "-comp", "xz")
	} else {
		if false {
			logv("Moving data directly into image...")
			utils.Run("mv", container.rwPath(), layerPath)
		} else {
			logv("Copying data into image...")
			utils.Run("cp", "-a", container.rwPath(), layerPath)
		}
	}

	jsonData, err := json.Marshal(img)

	if err != nil {
		panic(err)
	}

	err = ioutil.WriteFile(path.Join(root, "json"), jsonData, 0644)

	if err != nil {
		panic(err)
	}

	err = os.Rename(root, path.Join(DIR, "graph", img.ID))

	if err != nil {
		panic(err)
	}

	return img, nil
}