diff --git a/commands/commands.go b/commands.go similarity index 99% rename from commands/commands.go rename to commands.go index 681c04961e..4bf3f8a9df 100644 --- a/commands/commands.go +++ b/commands.go @@ -1,4 +1,4 @@ -package commands +package docker import ( "bufio" @@ -6,7 +6,6 @@ import ( "encoding/json" "errors" "fmt" - "github.com/dotcloud/docker" "github.com/dotcloud/docker/auth" "github.com/dotcloud/docker/fs" "github.com/dotcloud/docker/future" @@ -24,7 +23,7 @@ import ( "time" ) -const VERSION = "0.0.1" +const VERSION = "0.0.2" func (srv *Server) Name() string { return "docker" @@ -589,7 +588,7 @@ func (srv *Server) CmdPs(stdin io.ReadCloser, stdout io.Writer, args ...string) if !*quiet { command := fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " ")) if !*fl_full { - command = docker.Trunc(command, 20) + command = Trunc(command, 20) } for idx, field := range []string{ /* ID */ container.Id, @@ -780,10 +779,10 @@ func (srv *Server) CmdLogs(stdin io.ReadCloser, stdout io.Writer, args ...string return errors.New("No such container: " + cmd.Arg(0)) } -func (srv *Server) CreateContainer(img *fs.Image, ports []int, user string, tty bool, openStdin bool, memory int64, comment string, cmd string, args ...string) (*docker.Container, error) { +func (srv *Server) CreateContainer(img *fs.Image, ports []int, user string, tty bool, openStdin bool, memory int64, comment string, cmd string, args ...string) (*Container, error) { id := future.RandomId()[:8] container, err := srv.containers.Create(id, cmd, args, img, - &docker.Config{ + &Config{ Hostname: id, Ports: ports, User: user, @@ -984,12 +983,12 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) return nil } -func New() (*Server, error) { +func NewServer() (*Server, error) { future.Seed() // if err != nil { // return nil, err // } - containers, err := docker.New() + containers, err := New() if err != nil { return nil, err } @@ -1040,6 +1039,6 @@ func (srv *Server) CmdWeb(stdin io.ReadCloser, stdout io.Writer, args ...string) } type Server struct { - containers *docker.Docker + containers *Docker images *fs.Store } diff --git a/contrib/README b/contrib/README new file mode 100644 index 0000000000..92b1d94433 --- /dev/null +++ b/contrib/README @@ -0,0 +1,4 @@ +The `contrib` directory contains scripts, images, and other helpful things +which are not part of the core docker distribution. Please note that they +could be out of date, since they do not receive the same attention as the +rest of the repository. diff --git a/install.sh b/contrib/install.sh old mode 100644 new mode 100755 similarity index 94% rename from install.sh rename to contrib/install.sh index 0cfba4ddc3..b0a998332e --- a/install.sh +++ b/contrib/install.sh @@ -38,14 +38,14 @@ fi echo "Downloading docker binary and uncompressing into /usr/local/bin..." curl -s http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz | tar -C /usr/local/bin --strip-components=1 -zxf- \ -docker-master/docker docker-master/dockerd +docker-master/docker if [ -f /etc/init/dockerd.conf ] then echo "Upstart script already exists." else echo "Creating /etc/init/dockerd.conf..." - echo "exec /usr/local/bin/dockerd" > /etc/init/dockerd.conf + echo "exec /usr/local/bin/docker -d" > /etc/init/dockerd.conf fi echo "Starting dockerd..." diff --git a/contrib/mkimage-busybox.sh b/contrib/mkimage-busybox.sh new file mode 100755 index 0000000000..6c091d2c4a --- /dev/null +++ b/contrib/mkimage-busybox.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Generate a very minimal filesystem based on busybox-static, +# and load it into the local docker under the name "busybox". + +BUSYBOX=$(which busybox) +[ "$BUSYBOX" ] || { + echo "Sorry, I could not locate busybox." + echo "Try 'apt-get install busybox-static'?" + exit 1 +} + +set -e +ROOTFS=/tmp/rootfs-busybox-$$-$RANDOM +mkdir $ROOTFS +cd $ROOTFS + +mkdir bin etc dev dev/pts lib proc sys tmp +touch etc/resolv.conf +cp /etc/nsswitch.conf etc/nsswitch.conf +echo root:x:0:0:root:/:/bin/sh > etc/passwd +echo root:x:0: > etc/group +ln -s lib lib64 +ln -s bin sbin +cp $BUSYBOX bin +for X in $(busybox --list) +do + ln -s busybox bin/$X +done +rm bin/init +ln bin/busybox bin/init +cp /lib/x86_64-linux-gnu/lib{pthread,c,dl,nsl,nss_*}.so.* lib +cp /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 lib +for X in console null ptmx random stdin stdout stderr tty urandom zero +do + cp -a /dev/$X dev +done + +tar -cf- . | docker put busybox +docker run -i -a -u root busybox /bin/echo Success. + diff --git a/docker.go b/docker.go index 8e8b19082a..7a1c6a00f7 100644 --- a/docker.go +++ b/docker.go @@ -76,10 +76,9 @@ func (docker *Docker) Destroy(container *Container) error { if err := container.Mountpoint.Umount(); err != nil { log.Printf("Unable to umount container %v: %v", container.Id, err) } - - if err := container.Mountpoint.Deregister(); err != nil { - log.Printf("Unable to deregiser mountpoint %v: %v", container.Mountpoint.Root, err) - } + } + if err := container.Mountpoint.Deregister(); err != nil { + log.Printf("Unable to deregiser mountpoint %v: %v", container.Mountpoint.Root, err) } if err := os.RemoveAll(container.Root); err != nil { log.Printf("Unable to remove filesystem for %v: %v", container.Id, err) @@ -109,6 +108,12 @@ func New() (*Docker, error) { } func NewFromDirectory(root string) (*Docker, error) { + docker_repo := path.Join(root, "containers") + + if err := os.MkdirAll(docker_repo, 0700); err != nil && !os.IsExist(err) { + return nil, err + } + store, err := fs.New(path.Join(root, "images")) if err != nil { return nil, err @@ -120,16 +125,12 @@ func NewFromDirectory(root string) (*Docker, error) { docker := &Docker{ root: root, - repository: path.Join(root, "containers"), + repository: docker_repo, containers: list.New(), Store: store, networkManager: netManager, } - if err := os.MkdirAll(docker.repository, 0700); err != nil && !os.IsExist(err) { - return nil, err - } - if err := docker.restore(); err != nil { return nil, err } diff --git a/docker/docker.go b/docker/docker.go index ad121a8f60..79fe582e97 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -3,7 +3,6 @@ package main import ( "flag" "github.com/dotcloud/docker" - "github.com/dotcloud/docker/commands" "github.com/dotcloud/docker/future" "github.com/dotcloud/docker/rcli" "github.com/dotcloud/docker/term" @@ -36,7 +35,7 @@ func main() { } func daemon() error { - service, err := commands.New() + service, err := docker.NewServer() if err != nil { return err } @@ -78,7 +77,7 @@ func runCommand(args []string) error { } } } else { - service, err := commands.New() + service, err := docker.NewServer() if err != nil { return err } diff --git a/docker_test.go b/docker_test.go index 3f51e8d84c..003ef5fa9b 100644 --- a/docker_test.go +++ b/docker_test.go @@ -4,17 +4,28 @@ import ( "github.com/dotcloud/docker/fs" "io" "io/ioutil" - "log" "os" + "os/exec" "testing" ) const testLayerPath string = "/var/lib/docker/docker-ut.tar" +const unitTestImageName string = "busybox" + +var unitTestStoreBase string +var srv *Server func nuke(docker *Docker) error { return os.RemoveAll(docker.root) } +func CopyDirectory(source, dest string) error { + if _, err := exec.Command("cp", "-ra", source, dest).Output(); err != nil { + return err + } + return nil +} + func layerArchive(tarfile string) (io.Reader, error) { // FIXME: need to close f somewhere f, err := os.Open(tarfile) @@ -28,15 +39,29 @@ func init() { // Hack to run sys init during unit testing if SelfPath() == "/sbin/init" { SysInit() + return } - // Make sure the unit test image is there - if _, err := os.Stat(testLayerPath); err != nil { - if !os.IsNotExist(err) { - panic(err) - } - log.Fatalf("Unit test base image not found. Please fix the problem by running \"debootstrap --arch=amd64 quantal %v\"", testLayerPath) - return + // Create a temp directory + root, err := ioutil.TempDir("", "docker-test") + if err != nil { + panic(err) + } + unitTestStoreBase = root + + // Make it our Store root + docker, err := NewFromDirectory(root) + if err != nil { + panic(err) + } + // Create the "Server" + srv := &Server{ + images: docker.Store, + containers: docker, + } + // Retrieve the Image + if err := srv.CmdImport(os.Stdin, os.Stdout, unitTestImageName); err != nil { + panic(err) } } @@ -45,19 +70,19 @@ func newTestDocker() (*Docker, error) { if err != nil { return nil, err } + if err := os.Remove(root); err != nil { + return nil, err + } + if err := CopyDirectory(unitTestStoreBase, root); err != nil { + panic(err) + return nil, err + } + docker, err := NewFromDirectory(root) if err != nil { return nil, err } - if layer, err := layerArchive(testLayerPath); err != nil { - panic(err) - } else { - _, err = docker.Store.Create(layer, nil, "docker-ut", "unit tests") - if err != nil { - panic(err) - } - } return docker, nil } @@ -231,25 +256,22 @@ func TestGet(t *testing.T) { } func TestRestore(t *testing.T) { + root, err := ioutil.TempDir("", "docker-test") if err != nil { t.Fatal(err) } + if err := os.Remove(root); err != nil { + t.Fatal(err) + } + if err := CopyDirectory(unitTestStoreBase, root); err != nil { + t.Fatal(err) + } docker1, err := NewFromDirectory(root) if err != nil { t.Fatal(err) } - defer nuke(docker1) - - if layer, err := layerArchive(testLayerPath); err != nil { - panic(err) - } else { - _, err = docker1.Store.Create(layer, nil, "docker-ut", "unit tests") - if err != nil { - panic(err) - } - } // Create a container with one instance of docker container1, err := docker1.Create( diff --git a/dockerd/dockerweb.html b/dockerd/dockerweb.html deleted file mode 100755 index da1e61f0ea..0000000000 --- a/dockerd/dockerweb.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - - - - - - - - - - -
- - - diff --git a/fs/layers.go b/fs/layers.go index 5aca668731..dc7e621f85 100644 --- a/fs/layers.go +++ b/fs/layers.go @@ -93,7 +93,7 @@ func (store *LayerStore) AddLayer(id string, archive Archive) (string, error) { return "", fmt.Errorf("Mktemp failed: %s", err) } if err := Untar(archive, tmp); err != nil { - return "", nil + return "", err } layer := store.layerPath(id) if !store.Exists(id) { diff --git a/fs/store.go b/fs/store.go index 596d1ab62c..1243694fe1 100644 --- a/fs/store.go +++ b/fs/store.go @@ -112,7 +112,7 @@ func (store *Store) Remove(img *Image) error { func (store *Store) List(pth string) ([]*Image, error) { pth = path.Clean(pth) - images, err := store.orm.Select(Image{}, "select images.* from images, paths where Path=? and paths.Image=images.Id", pth) + images, err := store.orm.Select(Image{}, "select images.* from images, paths where Path=? and paths.Image=images.Id order by images.Created desc", pth) if err != nil { return nil, err } diff --git a/future/future.go b/future/future.go index e7f3d9289c..21b0eee385 100644 --- a/future/future.go +++ b/future/future.go @@ -101,25 +101,30 @@ func Download(url string, stderr io.Writer) (*http.Response, error) { // Reader with progress bar type progressReader struct { - reader io.ReadCloser // Stream to read from - output io.Writer // Where to send progress bar to - read_total int // Expected stream length (bytes) - read_progress int // How much has been read so far (bytes) - last_update int // How many bytes read at least update + reader io.ReadCloser // Stream to read from + output io.Writer // Where to send progress bar to + read_total int // Expected stream length (bytes) + read_progress int // How much has been read so far (bytes) + last_update int // How many bytes read at least update } + func (r *progressReader) Read(p []byte) (n int, err error) { read, err := io.ReadCloser(r.reader).Read(p) r.read_progress += read // Only update progress for every 1% read update_every := int(0.01 * float64(r.read_total)) - if r.read_progress - r.last_update > update_every { - fmt.Fprintf(r.output, "%d/%d (%.0f%%)\r", + if r.read_progress-r.last_update > update_every || r.read_progress == r.read_total { + fmt.Fprintf(r.output, "%d/%d (%.0f%%)\r", r.read_progress, r.read_total, - float64(r.read_progress) / float64(r.read_total) * 100) + float64(r.read_progress)/float64(r.read_total)*100) r.last_update = r.read_progress } + // Send newline when complete + if err == io.EOF { + fmt.Fprintf(r.output, "\n") + } return read, err }