builder.go
27319da0
 package docker
 
 import (
 	"fmt"
a3f6054f
 	"github.com/dotcloud/docker/utils"
f911ccc2
 	"os"
 	"path"
 	"time"
27319da0
 )
 
84d68007
 var defaultDns = []string{"8.8.8.8", "8.8.4.4"}
 
27319da0
 type Builder struct {
f911ccc2
 	runtime      *Runtime
 	repositories *TagStore
35c59f4e
 	graph        *Graph
0f312113
 
 	config *Config
 	image  *Image
27319da0
 }
 
 func NewBuilder(runtime *Runtime) *Builder {
 	return &Builder{
f911ccc2
 		runtime:      runtime,
35c59f4e
 		graph:        runtime.graph,
f911ccc2
 		repositories: runtime.repositories,
27319da0
 	}
 }
 
f911ccc2
 func (builder *Builder) Create(config *Config) (*Container, error) {
 	// Lookup image
 	img, err := builder.repositories.LookupImage(config.Image)
 	if err != nil {
 		return nil, err
6c168a89
 	}
9959e2cd
 
 	if img.Config != nil {
0f312113
 		MergeConfig(config, img.Config)
9959e2cd
 	}
 
42b1ea48
 	if config.Cmd == nil || len(config.Cmd) == 0 {
9959e2cd
 		return nil, fmt.Errorf("No command specified")
 	}
 
f911ccc2
 	// Generate id
fd224ee5
 	id := GenerateID()
f911ccc2
 	// Generate default hostname
 	// FIXME: the lxc template no longer needs to set a default hostname
 	if config.Hostname == "" {
 		config.Hostname = id[:12]
6c168a89
 	}
f911ccc2
 
 	container := &Container{
 		// FIXME: we should generate the ID here instead of receiving it as an argument
fd224ee5
 		ID:              id,
f911ccc2
 		Created:         time.Now(),
 		Path:            config.Cmd[0],
 		Args:            config.Cmd[1:], //FIXME: de-duplicate from config
 		Config:          config,
fd224ee5
 		Image:           img.ID, // Always use the resolved image id
f911ccc2
 		NetworkSettings: &NetworkSettings{},
 		// FIXME: do we need to store this in the container?
 		SysInitPath: sysInitPath,
 	}
fd224ee5
 	container.root = builder.runtime.containerRoot(container.ID)
f911ccc2
 	// 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
6c168a89
 	}
 
a3f6054f
 	if len(config.Dns) == 0 && len(builder.runtime.Dns) == 0 && utils.CheckLocalDns() {
 		//"WARNING: Docker detected local DNS server on resolv.conf. Using default external servers: %v", defaultDns
 		builder.runtime.Dns = defaultDns
 	}
 
f911ccc2
 	// If custom dns exists, then create a resolv.conf for the container
84d68007
 	if len(config.Dns) > 0 || len(builder.runtime.Dns) > 0 {
 		var dns []string
 		if len(config.Dns) > 0 {
 			dns = config.Dns
 		} else {
 			dns = builder.runtime.Dns
 		}
f911ccc2
 		container.ResolvConfPath = path.Join(container.root, "resolv.conf")
 		f, err := os.Create(container.ResolvConfPath)
 		if err != nil {
 			return nil, err
 		}
 		defer f.Close()
84d68007
 		for _, dns := range dns {
f911ccc2
 			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 {
6f212538
 		return nil, err
27319da0
 	}
f911ccc2
 	// Step 3: register the container
 	if err := builder.runtime.Register(container); err != nil {
27319da0
 		return nil, err
 	}
 	return container, nil
 }
 
9959e2cd
 // Commit creates a new filesystem image from the current state of a container.
 // The image can optionally be tagged into a repository
 func (builder *Builder) Commit(container *Container, repository, tag, comment, author string, config *Config) (*Image, error) {
 	// FIXME: freeze the container before copying it to avoid data corruption?
 	// FIXME: this shouldn't be in commands.
 	rwTar, err := container.ExportRw()
f7c5e92a
 	if err != nil {
 		return nil, err
 	}
9959e2cd
 	// Create a new image from the container's base layers + a new layer from container changes
 	img, err := builder.graph.Create(rwTar, container, comment, author, config)
f7c5e92a
 	if err != nil {
 		return nil, err
 	}
35c59f4e
 	// Register the image if needed
 	if repository != "" {
fd224ee5
 		if err := builder.repositories.Set(repository, tag, img.ID, true); err != nil {
35c59f4e
 			return img, err
 		}
 	}
f7c5e92a
 	return img, nil
7bccdc0d
 }