merge from master

This commit is contained in:
Ken Cochrane 2013-03-14 18:23:45 -07:00
commit 18519f12ae
11 changed files with 129 additions and 280 deletions

View File

@ -1,4 +1,4 @@
package commands package docker
import ( import (
"bufio" "bufio"
@ -6,7 +6,6 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/auth" "github.com/dotcloud/docker/auth"
"github.com/dotcloud/docker/fs" "github.com/dotcloud/docker/fs"
"github.com/dotcloud/docker/future" "github.com/dotcloud/docker/future"
@ -24,7 +23,7 @@ import (
"time" "time"
) )
const VERSION = "0.0.1" const VERSION = "0.0.2"
func (srv *Server) Name() string { func (srv *Server) Name() string {
return "docker" return "docker"
@ -589,7 +588,7 @@ func (srv *Server) CmdPs(stdin io.ReadCloser, stdout io.Writer, args ...string)
if !*quiet { if !*quiet {
command := fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " ")) command := fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
if !*fl_full { if !*fl_full {
command = docker.Trunc(command, 20) command = Trunc(command, 20)
} }
for idx, field := range []string{ for idx, field := range []string{
/* ID */ container.Id, /* 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)) 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] id := future.RandomId()[:8]
container, err := srv.containers.Create(id, cmd, args, img, container, err := srv.containers.Create(id, cmd, args, img,
&docker.Config{ &Config{
Hostname: id, Hostname: id,
Ports: ports, Ports: ports,
User: user, User: user,
@ -984,12 +983,12 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string)
return nil return nil
} }
func New() (*Server, error) { func NewServer() (*Server, error) {
future.Seed() future.Seed()
// if err != nil { // if err != nil {
// return nil, err // return nil, err
// } // }
containers, err := docker.New() containers, err := New()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1040,6 +1039,6 @@ func (srv *Server) CmdWeb(stdin io.ReadCloser, stdout io.Writer, args ...string)
} }
type Server struct { type Server struct {
containers *docker.Docker containers *Docker
images *fs.Store images *fs.Store
} }

4
contrib/README Normal file
View File

@ -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.

4
install.sh → contrib/install.sh Normal file → Executable file
View File

@ -38,14 +38,14 @@ fi
echo "Downloading docker binary and uncompressing into /usr/local/bin..." echo "Downloading docker binary and uncompressing into /usr/local/bin..."
curl -s http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz | curl -s http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz |
tar -C /usr/local/bin --strip-components=1 -zxf- \ tar -C /usr/local/bin --strip-components=1 -zxf- \
docker-master/docker docker-master/dockerd docker-master/docker
if [ -f /etc/init/dockerd.conf ] if [ -f /etc/init/dockerd.conf ]
then then
echo "Upstart script already exists." echo "Upstart script already exists."
else else
echo "Creating /etc/init/dockerd.conf..." 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 fi
echo "Starting dockerd..." echo "Starting dockerd..."

40
contrib/mkimage-busybox.sh Executable file
View File

@ -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.

View File

@ -76,10 +76,9 @@ func (docker *Docker) Destroy(container *Container) error {
if err := container.Mountpoint.Umount(); err != nil { if err := container.Mountpoint.Umount(); err != nil {
log.Printf("Unable to umount container %v: %v", container.Id, err) log.Printf("Unable to umount container %v: %v", container.Id, err)
} }
}
if err := container.Mountpoint.Deregister(); err != nil { if err := container.Mountpoint.Deregister(); err != nil {
log.Printf("Unable to deregiser mountpoint %v: %v", container.Mountpoint.Root, err) log.Printf("Unable to deregiser mountpoint %v: %v", container.Mountpoint.Root, err)
}
} }
if err := os.RemoveAll(container.Root); err != nil { if err := os.RemoveAll(container.Root); err != nil {
log.Printf("Unable to remove filesystem for %v: %v", container.Id, err) 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) { 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")) store, err := fs.New(path.Join(root, "images"))
if err != nil { if err != nil {
return nil, err return nil, err
@ -120,16 +125,12 @@ func NewFromDirectory(root string) (*Docker, error) {
docker := &Docker{ docker := &Docker{
root: root, root: root,
repository: path.Join(root, "containers"), repository: docker_repo,
containers: list.New(), containers: list.New(),
Store: store, Store: store,
networkManager: netManager, networkManager: netManager,
} }
if err := os.MkdirAll(docker.repository, 0700); err != nil && !os.IsExist(err) {
return nil, err
}
if err := docker.restore(); err != nil { if err := docker.restore(); err != nil {
return nil, err return nil, err
} }

View File

@ -3,7 +3,6 @@ package main
import ( import (
"flag" "flag"
"github.com/dotcloud/docker" "github.com/dotcloud/docker"
"github.com/dotcloud/docker/commands"
"github.com/dotcloud/docker/future" "github.com/dotcloud/docker/future"
"github.com/dotcloud/docker/rcli" "github.com/dotcloud/docker/rcli"
"github.com/dotcloud/docker/term" "github.com/dotcloud/docker/term"
@ -36,7 +35,7 @@ func main() {
} }
func daemon() error { func daemon() error {
service, err := commands.New() service, err := docker.NewServer()
if err != nil { if err != nil {
return err return err
} }
@ -78,7 +77,7 @@ func runCommand(args []string) error {
} }
} }
} else { } else {
service, err := commands.New() service, err := docker.NewServer()
if err != nil { if err != nil {
return err return err
} }

View File

@ -4,17 +4,28 @@ import (
"github.com/dotcloud/docker/fs" "github.com/dotcloud/docker/fs"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"os" "os"
"os/exec"
"testing" "testing"
) )
const testLayerPath string = "/var/lib/docker/docker-ut.tar" const testLayerPath string = "/var/lib/docker/docker-ut.tar"
const unitTestImageName string = "busybox"
var unitTestStoreBase string
var srv *Server
func nuke(docker *Docker) error { func nuke(docker *Docker) error {
return os.RemoveAll(docker.root) 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) { func layerArchive(tarfile string) (io.Reader, error) {
// FIXME: need to close f somewhere // FIXME: need to close f somewhere
f, err := os.Open(tarfile) f, err := os.Open(tarfile)
@ -28,15 +39,29 @@ func init() {
// Hack to run sys init during unit testing // Hack to run sys init during unit testing
if SelfPath() == "/sbin/init" { if SelfPath() == "/sbin/init" {
SysInit() SysInit()
return
} }
// Make sure the unit test image is there // Create a temp directory
if _, err := os.Stat(testLayerPath); err != nil { root, err := ioutil.TempDir("", "docker-test")
if !os.IsNotExist(err) { if err != nil {
panic(err) panic(err)
} }
log.Fatalf("Unit test base image not found. Please fix the problem by running \"debootstrap --arch=amd64 quantal %v\"", testLayerPath) unitTestStoreBase = root
return
// 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 { if err != nil {
return nil, err 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) docker, err := NewFromDirectory(root)
if err != nil { if err != nil {
return nil, err 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 return docker, nil
} }
@ -231,25 +256,22 @@ func TestGet(t *testing.T) {
} }
func TestRestore(t *testing.T) { func TestRestore(t *testing.T) {
root, err := ioutil.TempDir("", "docker-test") root, err := ioutil.TempDir("", "docker-test")
if err != nil { if err != nil {
t.Fatal(err) 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) docker1, err := NewFromDirectory(root)
if err != nil { if err != nil {
t.Fatal(err) 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 // Create a container with one instance of docker
container1, err := docker1.Create( container1, err := docker1.Create(

File diff suppressed because one or more lines are too long

View File

@ -93,7 +93,7 @@ func (store *LayerStore) AddLayer(id string, archive Archive) (string, error) {
return "", fmt.Errorf("Mktemp failed: %s", err) return "", fmt.Errorf("Mktemp failed: %s", err)
} }
if err := Untar(archive, tmp); err != nil { if err := Untar(archive, tmp); err != nil {
return "", nil return "", err
} }
layer := store.layerPath(id) layer := store.layerPath(id)
if !store.Exists(id) { if !store.Exists(id) {

View File

@ -112,7 +112,7 @@ func (store *Store) Remove(img *Image) error {
func (store *Store) List(pth string) ([]*Image, error) { func (store *Store) List(pth string) ([]*Image, error) {
pth = path.Clean(pth) 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 { if err != nil {
return nil, err return nil, err
} }

View File

@ -101,25 +101,30 @@ func Download(url string, stderr io.Writer) (*http.Response, error) {
// Reader with progress bar // Reader with progress bar
type progressReader struct { type progressReader struct {
reader io.ReadCloser // Stream to read from reader io.ReadCloser // Stream to read from
output io.Writer // Where to send progress bar to output io.Writer // Where to send progress bar to
read_total int // Expected stream length (bytes) read_total int // Expected stream length (bytes)
read_progress int // How much has been read so far (bytes) read_progress int // How much has been read so far (bytes)
last_update int // How many bytes read at least update last_update int // How many bytes read at least update
} }
func (r *progressReader) Read(p []byte) (n int, err error) { func (r *progressReader) Read(p []byte) (n int, err error) {
read, err := io.ReadCloser(r.reader).Read(p) read, err := io.ReadCloser(r.reader).Read(p)
r.read_progress += read r.read_progress += read
// Only update progress for every 1% read // Only update progress for every 1% read
update_every := int(0.01 * float64(r.read_total)) update_every := int(0.01 * float64(r.read_total))
if r.read_progress - r.last_update > update_every { if r.read_progress-r.last_update > update_every || r.read_progress == r.read_total {
fmt.Fprintf(r.output, "%d/%d (%.0f%%)\r", fmt.Fprintf(r.output, "%d/%d (%.0f%%)\r",
r.read_progress, r.read_progress,
r.read_total, 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 r.last_update = r.read_progress
} }
// Send newline when complete
if err == io.EOF {
fmt.Fprintf(r.output, "\n")
}
return read, err return read, err
} }