Bladeren bron

Merged branch 28-standalone

Solomon Hykes 12 jaren geleden
bovenliggende
commit
89245360e8
10 gewijzigde bestanden met toevoegingen van 170 en 194 verwijderingen
  1. 0 1
      .gitignore
  2. 84 17
      README.md
  3. 0 126
      client/client.go
  4. 1 10
      commands/commands.go
  5. 77 13
      docker/docker.go
  6. 0 24
      dockerd/dockerd.go
  7. 5 0
      rcli/types.go
  8. 1 1
      term/term.go
  9. 1 1
      term/termios_darwin.go
  10. 1 1
      term/termios_linux.go

+ 0 - 1
.gitignore

@@ -1,6 +1,5 @@
 .vagrant
 .vagrant
 docker/docker
 docker/docker
-dockerd/dockerd
 .*.swp
 .*.swp
 a.out
 a.out
 *.orig
 *.orig

+ 84 - 17
README.md

@@ -50,11 +50,37 @@ Under the hood, Docker is built on the following components:
 * [lxc](http://lxc.sourceforge.net/), a set of convenience scripts to simplify the creation of linux containers.
 * [lxc](http://lxc.sourceforge.net/), a set of convenience scripts to simplify the creation of linux containers.
 
 
 
 
-Setup instructions
+Install instructions
 ==================
 ==================
 
 
-Requirements
-------------
+Installing on Ubuntu 12.04 and 12.10
+------------------------------------
+
+1. Install dependencies:
+
+```bash
+        sudo apt-get install lxc wget bsdtar curl
+```
+
+2. Install the latest docker binary:
+
+```bash
+	wget http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz
+	tar -xf docker-master.tgz
+```
+
+3. Run your first container!
+
+```bash
+	cd docker-master
+	sudo ./docker import base
+	sudo ./docker run -a -i -t base /bin/bash
+```
+
+Consider adding docker to your `PATH` for simplicity.
+
+Installing on other Linux distributions
+---------------------------------------
 
 
 Right now, the officially supported distributions are:
 Right now, the officially supported distributions are:
 
 
@@ -64,27 +90,68 @@ Right now, the officially supported distributions are:
 Docker probably works on other distributions featuring a recent kernel, the AUFS patch, and up-to-date lxc. However this has not been tested.
 Docker probably works on other distributions featuring a recent kernel, the AUFS patch, and up-to-date lxc. However this has not been tested.
 
 
 
 
-Installation
----------------
+Usage examples
+==============
+
+Running an interactive shell
+----------------------------
+
+```bash
+	# Download a base image
+	docker import base
+
+	# Run an interactive shell in the base image,
+	# allocate a tty, attach stdin and stdout
+	docker run -a -i -t base /bin/bash
+```
+
+
+Starting a long-running worker process
+--------------------------------------
+
+```bash
+	# Run docker in daemon mode
+	(docker -d || echo "Docker daemon already running") &
+
+	# Start a very useful long-running process
+	JOB=$(docker run /bin/sh -c "while true; do echo Hello world!; sleep 1; done")
+
+	# Collect the output of the job so far
+	docker logs $JOB
+
+	# Kill the job
+	docker kill $JOB
+```
+
+
+Listing all running containers
+------------------------------
+
+```bash
+	docker ps
+```
+
+
+Expose a service on a TCP port
+------------------------------
 
 
-1. Set up your host of choice on a physical / virtual machine
-2. Assume root identity on your newly installed environment (`sudo -s`)
-3. Type the following commands:
+```bash
+	# Expose port 4444 of this container, and tell netcat to listen on it
+	JOB=$(docker run -p 4444 base /bin/nc -l -p 4444)
 
 
-        apt-get install lxc wget bsdtar curl
+	# Which public port is NATed to my container?
+	PORT=$(docker port $JOB 4444)
 
 
-4. Download the latest docker binaries: `wget http://get.docker.io/builds/$(uname -s)/$(uname -m)/docker-master.tgz` ([Or get the Linux/x86_64 binaries here](http://get.docker.io/builds/Linux/x86_64/docker-master.tgz) )
-5. Extract the contents of the tar file `tar -xf docker-master.tar.gz`
-6. Launch the docker daemon in the background `./dockerd &`
-7. Download a base image `./docker pull base`
-8. Run your first container! `./docker run -i -a -t base /bin/bash`
-9. Start exploring `./docker --help`
+	# Connect to the public port via the host's public address
+	echo hello world | nc $(hostname) $PORT
 
 
-Consider adding docker and dockerd to your `PATH` for simplicity.
+	# Verify that the network connection worked
+	echo "Daemon received: $(docker logs $JOB)"
+```
 
 
 
 
 What is a Standard Container?
 What is a Standard Container?
------------------------------
+=============================
 
 
 Docker defines a unit of software delivery called a Standard Container. The goal of a Standard Container is to encapsulate a software component and all its dependencies in
 Docker defines a unit of software delivery called a Standard Container. The goal of a Standard Container is to encapsulate a software component and all its dependencies in
 a format that is self-describing and portable, so that any compliant runtime can run it without extra dependency, regardless of the underlying machine and the contents of the container.
 a format that is self-describing and portable, so that any compliant runtime can run it without extra dependency, regardless of the underlying machine and the contents of the container.

+ 0 - 126
client/client.go

@@ -1,126 +0,0 @@
-package client
-
-import (
-	"github.com/dotcloud/docker/future"
-	"github.com/dotcloud/docker/rcli"
-	"io"
-	"io/ioutil"
-	"log"
-	"os"
-	"os/exec"
-	"path"
-	"path/filepath"
-)
-
-// Run docker in "simple mode": run a single command and return.
-func SimpleMode(args []string) error {
-	var oldState *State
-	var err error
-	if IsTerminal(0) && os.Getenv("NORAW") == "" {
-		oldState, err = MakeRaw(0)
-		if err != nil {
-			return err
-		}
-		defer Restore(0, oldState)
-	}
-	// FIXME: we want to use unix sockets here, but net.UnixConn doesn't expose
-	// CloseWrite(), which we need to cleanly signal that stdin is closed without
-	// closing the connection.
-	// See http://code.google.com/p/go/issues/detail?id=3345
-	conn, err := rcli.Call("tcp", "127.0.0.1:4242", args...)
-	if err != nil {
-		return err
-	}
-	receive_stdout := future.Go(func() error {
-		_, err := io.Copy(os.Stdout, conn)
-		return err
-	})
-	send_stdin := future.Go(func() error {
-		_, err := io.Copy(conn, os.Stdin)
-		if err := conn.CloseWrite(); err != nil {
-			log.Printf("Couldn't send EOF: " + err.Error())
-		}
-		return err
-	})
-	if err := <-receive_stdout; err != nil {
-		return err
-	}
-	if oldState != nil {
-		Restore(0, oldState)
-	}
-	if !IsTerminal(0) {
-		if err := <-send_stdin; err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// Run docker in "interactive mode": run a bash-compatible shell capable of running docker commands.
-func InteractiveMode(scripts ...string) error {
-	// Determine path of current docker binary
-	dockerPath, err := exec.LookPath(os.Args[0])
-	if err != nil {
-		return err
-	}
-	dockerPath, err = filepath.Abs(dockerPath)
-	if err != nil {
-		return err
-	}
-
-	// Create a temp directory
-	tmp, err := ioutil.TempDir("", "docker-shell")
-	if err != nil {
-		return err
-	}
-	defer os.RemoveAll(tmp)
-
-	// For each command, create an alias in temp directory
-	// FIXME: generate this list dynamically with introspection of some sort
-	// It might make sense to merge docker and dockerd to keep that introspection
-	// within a single binary.
-	for _, cmd := range []string{
-		"help",
-		"run",
-		"ps",
-		"pull",
-		"put",
-		"rm",
-		"kill",
-		"wait",
-		"stop",
-		"start",
-		"restart",
-		"logs",
-		"diff",
-		"commit",
-		"attach",
-		"info",
-		"tar",
-		"web",
-		"images",
-		"docker",
-	} {
-		if err := os.Symlink(dockerPath, path.Join(tmp, cmd)); err != nil {
-			return err
-		}
-	}
-
-	// Run $SHELL with PATH set to temp directory
-	rcfile, err := ioutil.TempFile("", "docker-shell-rc")
-	if err != nil {
-		return err
-	}
-	defer os.Remove(rcfile.Name())
-	io.WriteString(rcfile, "enable -n help\n")
-	os.Setenv("PATH", tmp+":"+os.Getenv("PATH"))
-	os.Setenv("PS1", "\\h docker> ")
-	shell := exec.Command("/bin/bash", append([]string{"--rcfile", rcfile.Name()}, scripts...)...)
-	shell.Stdin = os.Stdin
-	shell.Stdout = os.Stdout
-	shell.Stderr = os.Stderr
-	if err := shell.Run(); err != nil {
-		return err
-	}
-	return nil
-}

+ 1 - 10
server/server.go → commands/commands.go

@@ -1,4 +1,4 @@
-package server
+package commands
 
 
 import (
 import (
 	"bufio"
 	"bufio"
@@ -24,15 +24,6 @@ import (
 
 
 const VERSION = "0.0.1"
 const VERSION = "0.0.1"
 
 
-func (srv *Server) ListenAndServe() error {
-	go rcli.ListenAndServeHTTP("127.0.0.1:8080", srv)
-	// FIXME: we want to use unix sockets here, but net.UnixConn doesn't expose
-	// CloseWrite(), which we need to cleanly signal that stdin is closed without
-	// closing the connection.
-	// See http://code.google.com/p/go/issues/detail?id=3345
-	return rcli.ListenAndServe("tcp", "127.0.0.1:4242", srv)
-}
-
 func (srv *Server) Name() string {
 func (srv *Server) Name() string {
 	return "docker"
 	return "docker"
 }
 }

+ 77 - 13
docker/docker.go

@@ -2,28 +2,92 @@ package main
 
 
 import (
 import (
 	"flag"
 	"flag"
-	"github.com/dotcloud/docker/client"
+	"github.com/dotcloud/docker"
+	"github.com/dotcloud/docker/commands"
+	"github.com/dotcloud/docker/future"
+	"github.com/dotcloud/docker/rcli"
+	"github.com/dotcloud/docker/term"
+	"io"
 	"log"
 	"log"
 	"os"
 	"os"
-	"path"
 )
 )
 
 
 func main() {
 func main() {
-	if cmd := path.Base(os.Args[0]); cmd == "docker" {
-		fl_shell := flag.Bool("i", false, "Interactive mode")
-		flag.Parse()
-		if *fl_shell {
-			if err := client.InteractiveMode(flag.Args()...); err != nil {
-				log.Fatal(err)
+	if docker.SelfPath() == "/sbin/init" {
+		// Running in init mode
+		docker.SysInit()
+		return
+	}
+	fl_daemon := flag.Bool("d", false, "Daemon mode")
+	flag.Parse()
+	if *fl_daemon {
+		if flag.NArg() != 0 {
+			flag.Usage()
+			return
+		}
+		if err := daemon(); err != nil {
+			log.Fatal(err)
+		}
+	} else {
+		if err := runCommand(flag.Args()); err != nil {
+			log.Fatal(err)
+		}
+	}
+}
+
+func daemon() error {
+	service, err := commands.New()
+	if err != nil {
+		return err
+	}
+	return rcli.ListenAndServe("tcp", "127.0.0.1:4242", service)
+}
+
+func runCommand(args []string) error {
+	var oldState *term.State
+	var err error
+	if term.IsTerminal(0) && os.Getenv("NORAW") == "" {
+		oldState, err = term.MakeRaw(0)
+		if err != nil {
+			return err
+		}
+		defer term.Restore(0, oldState)
+	}
+	// FIXME: we want to use unix sockets here, but net.UnixConn doesn't expose
+	// CloseWrite(), which we need to cleanly signal that stdin is closed without
+	// closing the connection.
+	// See http://code.google.com/p/go/issues/detail?id=3345
+	if conn, err := rcli.Call("tcp", "127.0.0.1:4242", args...); err == nil {
+		receive_stdout := future.Go(func() error {
+			_, err := io.Copy(os.Stdout, conn)
+			return err
+		})
+		send_stdin := future.Go(func() error {
+			_, err := io.Copy(conn, os.Stdin)
+			if err := conn.CloseWrite(); err != nil {
+				log.Printf("Couldn't send EOF: " + err.Error())
 			}
 			}
-		} else {
-			if err := client.SimpleMode(os.Args[1:]); err != nil {
-				log.Fatal(err)
+			return err
+		})
+		if err := <-receive_stdout; err != nil {
+			return err
+		}
+		if !term.IsTerminal(0) {
+			if err := <-send_stdin; err != nil {
+				return err
 			}
 			}
 		}
 		}
 	} else {
 	} else {
-		if err := client.SimpleMode(append([]string{cmd}, os.Args[1:]...)); err != nil {
-			log.Fatal(err)
+		service, err := commands.New()
+		if err != nil {
+			return err
 		}
 		}
+		if err := rcli.LocalCall(service, os.Stdin, os.Stdout, args...); err != nil {
+			return err
+		}
+	}
+	if oldState != nil {
+		term.Restore(0, oldState)
 	}
 	}
+	return nil
 }
 }

+ 0 - 24
dockerd/dockerd.go

@@ -1,24 +0,0 @@
-package main
-
-import (
-	"flag"
-	"github.com/dotcloud/docker"
-	"github.com/dotcloud/docker/server"
-	"log"
-)
-
-func main() {
-	if docker.SelfPath() == "/sbin/init" {
-		// Running in init mode
-		docker.SysInit()
-		return
-	}
-	flag.Parse()
-	d, err := server.New()
-	if err != nil {
-		log.Fatal(err)
-	}
-	if err := d.ListenAndServe(); err != nil {
-		log.Fatal(err)
-	}
-}

+ 5 - 0
rcli/types.go

@@ -25,7 +25,12 @@ type Service interface {
 type Cmd func(io.ReadCloser, io.Writer, ...string) error
 type Cmd func(io.ReadCloser, io.Writer, ...string) error
 type CmdMethod func(Service, io.ReadCloser, io.Writer, ...string) error
 type CmdMethod func(Service, io.ReadCloser, io.Writer, ...string) error
 
 
+// FIXME: For reverse compatibility
 func call(service Service, stdin io.ReadCloser, stdout io.Writer, args ...string) error {
 func call(service Service, stdin io.ReadCloser, stdout io.Writer, args ...string) error {
+	return LocalCall(service, stdin, stdout, args...)
+}
+
+func LocalCall(service Service, stdin io.ReadCloser, stdout io.Writer, args ...string) error {
 	if len(args) == 0 {
 	if len(args) == 0 {
 		args = []string{"help"}
 		args = []string{"help"}
 	}
 	}

+ 1 - 1
client/term.go → term/term.go

@@ -1,4 +1,4 @@
-package client
+package term
 
 
 import (
 import (
 	"syscall"
 	"syscall"

+ 1 - 1
client/termios_darwin.go → term/termios_darwin.go

@@ -1,4 +1,4 @@
-package client
+package term
 
 
 import "syscall"
 import "syscall"
 
 

+ 1 - 1
client/termios_linux.go → term/termios_linux.go

@@ -1,4 +1,4 @@
-package client
+package term
 
 
 import "syscall"
 import "syscall"