diff --git a/README.md b/README.md index c1c155ac73..0a9b69c6de 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ Docker: the Linux container runtime =================================== -Docker complements LXC with a high-level API with operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers. +Docker complements LXC with a high-level API which operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers. -Is is a great building block for automating distributed systems: large-scale web deployments, database clusters, continuous deployment systems, private PaaS, service-oriented architectures, etc. +Docker is a great building block for automating distributed systems: large-scale web deployments, database clusters, continuous deployment systems, private PaaS, service-oriented architectures, etc. @@ -27,7 +27,7 @@ Notable features * Copy-on-write: root filesystems are created using copy-on-write, which makes deployment extremeley fast, memory-cheap and disk-cheap. -* Logging: the standard streams (stdout/stderr/stdin) of each process container is collected and logged for real-time or batch retrieval. +* Logging: the standard streams (stdout/stderr/stdin) of each process container are collected and logged for real-time or batch retrieval. * Change management: changes to a container's filesystem can be committed into a new image and re-used to create more containers. No templating or manual configuration required. @@ -58,28 +58,28 @@ Installing on Ubuntu 12.04 and 12.10 1. Install dependencies: -```bash - sudo apt-get install lxc wget bsdtar curl - sudo apt-get install linux-image-extra-`uname -r` -``` + ```bash + sudo apt-get install lxc wget bsdtar curl + sudo apt-get install linux-image-extra-`uname -r` + ``` -The `linux-image-extra` package is needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module. + The `linux-image-extra` package is needed on standard Ubuntu EC2 AMIs in order to install the aufs kernel module. 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 -``` + ```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 run -a -i -t base /bin/bash -``` + ```bash + cd docker-master + sudo ./docker run -a -i -t base /bin/bash + ``` -Consider adding docker to your `PATH` for simplicity. + Consider adding docker to your `PATH` for simplicity. Installing on other Linux distributions --------------------------------------- @@ -99,12 +99,12 @@ with VirtualBox as well as on Amazon EC2. Vagrant 1.1 is required for EC2, but deploying is as simple as: ```bash - $ export AWS_ACCESS_KEY_ID=xxx \ - AWS_SECRET_ACCESS_KEY=xxx \ - AWS_KEYPAIR_NAME=xxx \ - AWS_SSH_PRIVKEY=xxx - $ vagrant plugin install vagrant-aws - $ vagrant up --provider=aws +$ export AWS_ACCESS_KEY_ID=xxx \ + AWS_SECRET_ACCESS_KEY=xxx \ + AWS_KEYPAIR_NAME=xxx \ + AWS_SSH_PRIVKEY=xxx +$ vagrant plugin install vagrant-aws +$ vagrant up --provider=aws ``` The environment variables are: @@ -115,11 +115,11 @@ The environment variables are: * `AWS_SSH_PRIVKEY` - The path to the private key for the named keypair For VirtualBox, you can simply ignore setting any of the environment -variables and omit the ``provider`` flag. VirtualBox is still supported with -Vagrant <= 1.1: +variables and omit the `provider` flag. VirtualBox is still supported with +Vagrant <= 1.1: ```bash - $ vagrant up +$ vagrant up ``` @@ -131,12 +131,12 @@ Running an interactive shell ---------------------------- ```bash - # Download a base image - docker import base +# 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 +# Run an interactive shell in the base image, +# allocate a tty, attach stdin and stdout +docker run -a -i -t base /bin/bash ``` @@ -144,17 +144,17 @@ Starting a long-running worker process -------------------------------------- ```bash - # Run docker in daemon mode - (docker -d || echo "Docker daemon already running") & +# Run docker in daemon mode +(docker -d || echo "Docker daemon already running") & - # Start a very useful long-running process - JOB=$(docker run base /bin/sh -c "while true; do echo Hello world; sleep 1; done") +# Start a very useful long-running process +JOB=$(docker run base /bin/sh -c "while true; do echo Hello world; sleep 1; done") - # Collect the output of the job so far - docker logs $JOB +# Collect the output of the job so far +docker logs $JOB - # Kill the job - docker kill $JOB +# Kill the job +docker kill $JOB ``` @@ -162,7 +162,7 @@ Listing all running containers ------------------------------ ```bash - docker ps +docker ps ``` @@ -170,17 +170,17 @@ Expose a service on a TCP port ------------------------------ ```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) +# Expose port 4444 of this container, and tell netcat to listen on it +JOB=$(docker run -p 4444 base /bin/nc -l -p 4444) - # Which public port is NATed to my container? - PORT=$(docker port $JOB 4444) +# Which public port is NATed to my container? +PORT=$(docker port $JOB 4444) - # Connect to the public port via the host's public address - echo hello world | nc $(hostname) $PORT +# Connect to the public port via the host's public address +echo hello world | nc $(hostname) $PORT - # Verify that the network connection worked - echo "Daemon received: $(docker logs $JOB)" +# Verify that the network connection worked +echo "Daemon received: $(docker logs $JOB)" ``` Contributing to Docker @@ -195,10 +195,10 @@ Contribution guidelines We are always thrilled to receive pull requests, and do our best to process them as fast as possible. Not sure if that typo is worth a pull request? Do it! We will appreciate it. -If your pull request is not accepted on the first try, don't be discouraged! If there's a problen with the implementation, hopefully you received feedback on what to improve. +If your pull request is not accepted on the first try, don't be discouraged! If there's a problem with the implementation, hopefully you received feedback on what to improve. We're trying very hard to keep Docker lean and focused. We don't want it to do everything for everybody. This means that we might decide against incorporating a new feature. -However there might be a way to implement that feature *on top of* docker. +However, there might be a way to implement that feature *on top of* docker. ### Discuss your design on the mailing list @@ -207,7 +207,7 @@ you in the right direction, give feedback on your design, and maybe point out if ### Create issues... -Any significant improvement should be documented as a github issue before anybody start working on it. +Any significant improvement should be documented as [a github issue](https://github.com/dotcloud/docker/issues) before anybody starts working on it. ### ...but check for existing issues first! @@ -224,9 +224,9 @@ Golang has a great testing suite built in: use it! Take a look at existing tests Setting up a dev environment ---------------------------- -Instructions that is verified to work on Ubuntu 12.10, +Instructions that have been verified to work on Ubuntu 12.10, -``` +```bash sudo apt-get -y install lxc wget bsdtar curl libsqlite3-dev golang git pkg-config export GOPATH=~/go/ @@ -243,7 +243,7 @@ go install -v github.com/dotcloud/docker/... Then run the docker daemon, -``` +```bash sudo $GOPATH/bin/docker -d ``` @@ -254,9 +254,9 @@ 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 -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 dependencies, regardless of the underlying machine and the contents of the container. -The spec for Standard Containers is currently work in progress, but it is very straightforward. It mostly defines 1) an image format, 2) a set of standard operations, and 3) an execution environment. +The spec for Standard Containers is currently a work in progress, but it is very straightforward. It mostly defines 1) an image format, 2) a set of standard operations, and 3) an execution environment. A great analogy for this is the shipping container. Just like Standard Containers are a fundamental unit of software delivery, shipping containers (http://bricks.argz.com/ins/7823-1/12) are a fundamental unit of physical delivery. diff --git a/Vagrantfile b/Vagrantfile index e847659848..4cf5f0a0e5 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -1,7 +1,7 @@ # -*- mode: ruby -*- # vi: set ft=ruby : -Vagrant.configure("1") do |config| +def v10(config) # All Vagrant configuration is done here. The most common configuration # options are documented and commented below. For a complete reference, # please see the online documentation at vagrantup.com. @@ -20,7 +20,7 @@ Vagrant.configure("1") do |config| # via the IP. Host-only networks can talk to the host machine as well as # any other machines on the same network, but cannot be accessed (through this # network interface) by any external networks. - # config.vm.network :hostonly, "192.168.33.10" + config.vm.network :hostonly, "192.168.33.10" # Assign this VM to a bridged network, allowing you to connect directly to a # network using the host's network device. This makes the VM appear as another @@ -34,6 +34,9 @@ Vagrant.configure("1") do |config| # Share an additional folder to the guest VM. The first argument is # an identifier, the second is the path on the guest to mount the # folder, and the third is the path on the host to the actual folder. + if not File.exist? File.expand_path '~/docker' + Dir.mkdir(File.expand_path '~/docker') + end config.vm.share_folder "v-data", "~/docker", "~/docker" # Enable provisioning with Puppet stand alone. Puppet manifests @@ -99,21 +102,29 @@ Vagrant.configure("1") do |config| # chef.validation_client_name = "ORGNAME-validator" end -Vagrant.configure("2") do |config| +"#{Vagrant::VERSION}" < "1.1.0" and Vagrant::Config.run do |config| + v10(config) +end + +"#{Vagrant::VERSION}" >= "1.1.0" and Vagrant.configure("1") do |config| + v10(config) +end + +"#{Vagrant::VERSION}" >= "1.1.0" and Vagrant.configure("2") do |config| config.vm.provider :aws do |aws| - config.vm.box = "dummy" - config.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box" + config.vm.box = "dummy" + config.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box" aws.access_key_id = ENV["AWS_ACCESS_KEY_ID"] - aws.secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"] - aws.keypair_name = ENV["AWS_KEYPAIR_NAME"] - aws.ssh_private_key_path = ENV["AWS_SSH_PRIVKEY"] - aws.region = "us-east-1" + aws.secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"] + aws.keypair_name = ENV["AWS_KEYPAIR_NAME"] + aws.ssh_private_key_path = ENV["AWS_SSH_PRIVKEY"] + aws.region = "us-east-1" aws.ami = "ami-1c1e8075" aws.ssh_username = "vagrant" - aws.instance_type = "t1.micro" + aws.instance_type = "t1.micro" end config.vm.provider :virtualbox do |vb| - config.vm.box = "quantal64_3.5.0-25" - config.vm.box_url = "http://get.docker.io/vbox/ubuntu/12.10/quantal64_3.5.0-25.box" - end + config.vm.box = "quantal64_3.5.0-25" + config.vm.box_url = "http://get.docker.io/vbox/ubuntu/12.10/quantal64_3.5.0-25.box" + end end diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..2abaac9393 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,4 @@ +Docs readme +=========== + +Let's see if this file shows up as we hope it does. diff --git a/network.go b/network.go index 01d84379a2..73cb1709af 100644 --- a/network.go +++ b/network.go @@ -95,7 +95,8 @@ func getIfaceAddr(name string) (net.Addr, error) { case len(addrs4) == 0: return nil, fmt.Errorf("Interface %v has no IP addresses", name) case len(addrs4) > 1: - return nil, fmt.Errorf("Interface %v has more than 1 IPv4 address", name) + fmt.Printf("Interface %v has more than 1 IPv4 address. Defaulting to using %v\n", + name, (addrs4[0].(*net.IPNet)).IP) } return addrs4[0], nil } @@ -123,6 +124,9 @@ func (mapper *PortMapper) setup() error { if err := iptables("-t", "nat", "-A", "PREROUTING", "-j", "DOCKER"); err != nil { return errors.New("Unable to setup port networking: Failed to inject docker in PREROUTING chain") } + if err := iptables("-t", "nat", "-A", "OUTPUT", "-j", "DOCKER"); err != nil { + return errors.New("Unable to setup port networking: Failed to inject docker in OUTPUT chain") + } return nil } diff --git a/puppet/modules/docker/manifests/init.pp b/puppet/modules/docker/manifests/init.pp index 1862c524b8..6f8d249ff7 100644 --- a/puppet/modules/docker/manifests/init.pp +++ b/puppet/modules/docker/manifests/init.pp @@ -80,7 +80,7 @@ class docker { owner => "root", group => "root", content => template("docker/dockerd.conf"), - require => Exec["fetch-docker"], + require => Exec["copy-docker-bin"], } file { "/home/vagrant": diff --git a/puppet/modules/docker/templates/dockerd.conf b/puppet/modules/docker/templates/dockerd.conf index 2d77c301f0..f88d5c347f 100644 --- a/puppet/modules/docker/templates/dockerd.conf +++ b/puppet/modules/docker/templates/dockerd.conf @@ -8,5 +8,5 @@ respawn script test -f /etc/default/locale && . /etc/default/locale || true - LANG=$LANG LC_ALL=$LANG /usr/local/bin/docker -d + LANG=$LANG LC_ALL=$LANG /usr/local/bin/docker -d >> /var/log/dockerd 2>&1 end script diff --git a/term/term.go b/term/term.go index fdbe3b9984..39b77dcc59 100644 --- a/term/term.go +++ b/term/term.go @@ -114,27 +114,6 @@ func IsTerminal(fd int) bool { return err == 0 } -// MakeRaw put the terminal connected to the given file descriptor into raw -// mode and returns the previous state of the terminal so that it can be -// restored. -func MakeRaw(fd int) (*State, error) { - var oldState State - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { - return nil, err - } - - newState := oldState.termios - newState.Iflag &^= ISTRIP | INLCR | IGNCR | IXON | IXOFF - newState.Iflag |= ICRNL - newState.Oflag |= ONLCR - newState.Lflag &^= ECHO | ICANON | ISIG - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { - return nil, err - } - - return &oldState, nil -} - // Restore restores the terminal connected to the given file descriptor to a // previous state. func Restore(fd int, state *State) error { diff --git a/term/termios_darwin.go b/term/termios_darwin.go index 26d17b3bb8..4365b60339 100644 --- a/term/termios_darwin.go +++ b/term/termios_darwin.go @@ -1,8 +1,32 @@ package term -import "syscall" +import ( + "syscall" + "unsafe" +) const ( getTermios = syscall.TIOCGETA setTermios = syscall.TIOCSETA ) + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + var oldState State + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { + return nil, err + } + + newState := oldState.termios + newState.Iflag &^= ISTRIP | INLCR | IGNCR | IXON | IXOFF + newState.Iflag |= ICRNL + newState.Oflag |= ONLCR + newState.Lflag &^= ECHO | ICANON | ISIG + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { + return nil, err + } + + return &oldState, nil +} \ No newline at end of file diff --git a/term/termios_linux.go b/term/termios_linux.go index 1ea26fa5c4..933ef84c4d 100644 --- a/term/termios_linux.go +++ b/term/termios_linux.go @@ -1,8 +1,32 @@ package term -import "syscall" +import ( + "syscall" + "unsafe" +) const ( getTermios = syscall.TCGETS setTermios = syscall.TCSETS ) + +// MakeRaw put the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + var oldState State + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { + return nil, err + } + + newState := oldState.termios + newState.Iflag &^= ISTRIP | IXON | IXOFF + newState.Iflag |= ICRNL + newState.Oflag |= ONLCR + newState.Lflag &^= ECHO | ICANON | ISIG + if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { + return nil, err + } + + return &oldState, nil +} \ No newline at end of file