diff --git a/README.md b/README.md index c1c155ac73f3e7fb84ba03ae45a1aa5f9b68a8e0..0a9b69c6de25318b3dc0c8a5d1354852505851e2 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 e847659848ec29e4f98e14fe4e92d2412242950c..4cf5f0a0e5dbd0aa72456ae04f89e0237101fc98 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 0000000000000000000000000000000000000000..2abaac93931f9169faff201bdf6e4af958f622fb --- /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 01d84379a2cf8cff76a99fa0556b099b9871e039..73cb1709afbc0d4d79ece5a953112727f545216b 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 1862c524b8931daf102d12e68f5427565f346ad3..6f8d249ff7b5883592a4879e218547486b7ae298 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 2d77c301f055b3601627f66472b38480220e1e22..f88d5c347fe7b85c89eb0f9eb77e7a2f23512901 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 fdbe3b99842ccad275cb6864c8d16ab2ccbfe3c9..39b77dcc59f2b1fc37e4151121042749b95aa728 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 26d17b3bb8fb4bbfb8c5a5496c5a1d61883102b8..4365b603390ae2636f3a38999fbda763ba7d59b1 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 1ea26fa5c46d728aec62c84cf26a0ea589eb6f83..933ef84c4d6960bdcde2c53d60d079b3fa34ca39 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