Compare commits

...

65 Commits

Author SHA1 Message Date
Solomon Hykes e34e44e8e6 Bumped version to 0.1.5 2013-04-17 17:12:08 -07:00
Solomon Hykes 13d9e26edd Fix the behavior of Graph.Register so that it can be interrupted without side effect 2013-04-17 16:35:22 -07:00
Solomon Hykes 0a3131554c Merge pull request #406 from shawnsi/405-arch-docs
Issue #405: Documentation for Arch Linux Install
2013-04-17 15:45:26 -07:00
Solomon Hykes 521ce07859 Merge pull request #409 from lynaghk/master
Docker init created by contrib setup script should set proper UTF8 LANG
2013-04-17 15:23:12 -07:00
Solomon Hykes f02950965e Merge remote-tracking branch 'origin/183-no_such_device-fix' 2013-04-17 11:54:57 -07:00
Solomon Hykes 16f6daa5be Merge remote-tracking branch 'origin/416-lxc_0_9_compatibliity-fix' 2013-04-17 11:35:12 -07:00
Solomon Hykes ca6cd5b557 Keep a cache of the unit-tests image. So I can code in conferences with crappy wifi. 2013-04-17 11:32:13 -07:00
Guillaume J. Charmes c4cd224d90 improve the crashTest script 2013-04-16 15:20:04 -07:00
Guillaume J. Charmes 7b0e96f1f4 Manually pass the env to docker-init instead of relying on lxc to pass it 2013-04-16 14:32:50 -07:00
Solomon Hykes fc72a809c1 Remove unneeded dependencies from README 2013-04-16 12:10:16 -07:00
Solomon Hykes 2a47df0202 Disabled standalone mode (fixes #364) 2013-04-15 11:44:11 -07:00
Kevin J. Lynagh 468fb90117 install.sh script's dockerd.conf should set docker daemon environment's LANG to en_US.UTF-8. See #355. 2013-04-15 08:49:48 -07:00
Victor Vieux ac49a797b4 try to load aufs module, disply error on failure 2013-04-15 12:05:46 +02:00
Guillaume J. Charmes 1ec6c223c9 Add a script to help reproduce #407 2013-04-14 15:13:32 -07:00
Solomon Hykes db08705e3c Merge remote-tracking branch 'origin/packaging' 2013-04-13 21:40:53 -07:00
Solomon Hykes fdf3308260 Merge remote-tracking branch 'origin/396-disabling_memory_limit-feature' 2013-04-13 21:25:53 -07:00
Guillaume J. Charmes c2c72bcfd7 Add \r to error message in run raw mode 2013-04-13 15:03:24 -07:00
Solomon Hykes cdf90bb04b Merge remote-tracking branch 'origin/96-dns_issue-fix' 2013-04-12 17:50:59 -07:00
Shawn Siefkas 45809e9a05 Issue #405: Documentation for Arch Linux Install 2013-04-12 13:25:33 -05:00
Guillaume J. Charmes 1967c8342a Allow to disable memory limit at compilation time 2013-04-12 10:48:20 -07:00
Guillaume J. Charmes 7673afc843 Allow use to set his own dns via -dns 2013-04-12 10:43:13 -07:00
Solomon Hykes b1fbebb4a3 Fixed wording of ghost-related messages 2013-04-12 10:39:08 -07:00
Solomon Hykes 3527291b47 Merge remote-tracking branch 'origin/ghost_handling-fix' 2013-04-12 10:33:36 -07:00
Solomon Hykes 57d31c9777 Merge remote-tracking branch 'origin/kill_behaviour_fix' 2013-04-12 10:20:26 -07:00
Guillaume J. Charmes a2f5a56143 Merge pull request #403 from titanous/update-authors
Update AUTHORS
2013-04-12 07:56:19 -07:00
Jonathan Rudenberg 343ed6b53f Update AUTHORS 2013-04-12 10:44:50 -04:00
Guillaume J. Charmes 22893429ed Go fmt 2013-04-12 07:37:24 -07:00
Guillaume J. Charmes c1703c2b68 Merge branch 'create_pidfile' of https://github.com/flavio/docker into flavio-create_pidfile 2013-04-12 07:28:36 -07:00
Guillaume J. Charmes a8c15477d9 Merge pull request #381 from dotcloud/371-add-l-ps
Add options to docker ps
2013-04-12 07:16:00 -07:00
Guillaume J. Charmes 9d03b2bb62 Merge pull request #395 from dotcloud/commands_usage-fix
fixes some usages (multiple parameters mostly)
2013-04-12 07:03:36 -07:00
Victor Vieux 8987bd5832 removed not needed [OPTIONS] and remove poor messages like 'Not enough arguments' 2013-04-12 12:26:31 +02:00
Daniel Mizyrycki f226842aa1 Packaging, Debian: Add maintainer documentation 2013-04-11 20:17:41 -07:00
Daniel Mizyrycki b14164879b Packaging: Add README documentation 2013-04-11 17:39:47 -07:00
Guillaume J. Charmes bb22cd492e Add unit test for hanging kill + fix other tests behaviour 2013-04-11 16:21:19 -07:00
Solomon Hykes 27be5aec74 Merge pull request #386 from lopter/master
Use ip to setup the gateway in sysinit.go
2013-04-11 15:02:20 -07:00
Solomon Hykes 048f9f4974 Added docker-build (formerly github.com/shykes/changer) as a contrib script 2013-04-11 14:44:39 -07:00
Flavio Castelli fb0b375be7 docker daemon: create file containing PID
Ensure the docker daemon creates a file containing its PID under
/var/run/docker.pid.

The daemon takes care of removing the pid file when it receives either
SIGTERM, SIGINT or SIGKILL.

The daemon also refuses to start when the pidfile is found. An
explanation message is shown to the user when this happens.

This change is required to make docker easier to manage by tools like
checkproc which rely on this information.
2013-04-11 21:41:08 +02:00
Solomon Hykes 79d934bfb0 Simplify the output of 'docker images' by removing the PARENT column 2013-04-11 12:11:41 -07:00
Solomon Hykes 54dfedc516 Merge remote-tracking branch 'origin/148-remove_repositories-feature' 2013-04-11 11:36:28 -07:00
Solomon Hykes 0eb7157b6f Merge remote-tracking branch 'origin/crlf_on_raw_mode' 2013-04-11 11:31:17 -07:00
Solomon Hykes 2de953490d Contrib post-commit hook for checking gofmt 2013-04-11 11:30:35 -07:00
Victor Vieux 3ba44d2d5f fixes some usages 2013-04-11 18:46:47 +02:00
Guillaume J. Charmes 313d13ea01 Detect and mark ghost container. 2013-04-11 09:26:17 -07:00
Guillaume J. Charmes e68c04b722 force kill now use lxc-kill. Fixes #383 2013-04-11 09:04:04 -07:00
Guillaume J. Charmes c902c43766 Merge pull request #392 from dotcloud/rm_usage-fix
Display usage when no parameter in docker rm
2013-04-11 07:56:46 -07:00
Victor Vieux c105049f7e display usage when no parameter 2013-04-11 16:27:01 +02:00
Victor Vieux 17136d58f2 snake_case to camelCase 2013-04-11 13:09:40 +02:00
Daniel Mizyrycki 8ea1e9126f packaging; issue #251: Add debian packaging 2013-04-10 21:00:39 -07:00
Guillaume J. Charmes 6dc4c74b5a Use crlf in registry function to avoid issue with autlogin in push and autopull in run 2013-04-10 19:13:15 -07:00
Guillaume J. Charmes 9d1fd2317d use crlf in login in order to avoir issue due to real raw mode 2013-04-10 19:08:46 -07:00
Guillaume J. Charmes 1f9f5eed5d Put the resolv.conf path in a variable instead of being hardcoded within lxc 2013-04-10 18:23:34 -07:00
Louis Opter 5e1a975b48 Use ip to setup the gateway in sysinit.go
ip from iproute2 replaces the legacy route tool which is often not
installed by default on recent Linux distributions.

The same patch has been done in network.go and is re-used here.
2013-04-10 17:40:28 -07:00
Guillaume J. Charmes 97f48e59fc Allow rmi to remove image from its name 2013-04-10 17:23:42 -07:00
Solomon Hykes e41fd24542 Added temporary spec for data volumes as requested on #111 2013-04-10 13:57:26 -07:00
Victor Vieux 8bd192fb16 changed last to n 2013-04-10 21:09:21 +02:00
Victor Vieux 8c3331dc97 add -l to docker ps 2013-04-10 19:30:57 +02:00
Solomon Hykes f507188ddc Merge pull request #372 from srid/goroutine-scope
serve goroutine must refer to the local conn
2013-04-09 21:06:31 -07:00
Solomon Hykes 76b7b2adf7 Merge remote-tracking branch 'origin/wait_non_existing_container-fix' 2013-04-09 21:05:15 -07:00
Solomon Hykes a1f54cad6c Merge pull request #367 from johncosta/333-redis-documentation
Add documentation for running a redis process with docker
2013-04-09 18:16:39 -07:00
Guillaume J. Charmes 9f83b9df22 Make sure all containers (even previously stopped) get a correct wait lock 2013-04-09 17:40:02 -07:00
John Costa 4ab241c930 incorporate feedback for improving the PR 2013-04-09 18:04:01 -04:00
Sridhar Ratnakumar f731835e45 serve goroutine must refer to the local conn 2013-04-09 15:00:05 -07:00
John Costa 418ef43fbb Merge github.com:dotcloud/docker into 333-redis-documentation 2013-04-09 16:07:40 -04:00
John Costa 8f15c423e6 add documentation for running a redis process with docker 2013-04-09 11:04:14 -04:00
Daniel Mizyrycki e99541e637 packaging; issue #30: Original files to make the Ubuntu PPA on launch date 2013-03-29 14:57:31 -07:00
59 changed files with 1359 additions and 127 deletions
+3
View File
@@ -14,3 +14,6 @@ Joffrey F <joffrey@dotcloud.com>
<joffrey@dotcloud.com> <f.joffrey@gmail.com>
Tim Terhorst <mynamewastaken+git@gmail.com>
Andy Smith <github@anarkystic.com>
<kalessin@kalessin.fr> <louis@dotcloud.com>
<victor.vieux@dotcloud.com> <victor@dotcloud.com>
<dominik@honnef.co> <dominikh@fork-bomb.org>
+7
View File
@@ -10,6 +10,8 @@ Daniel Robinson <gottagetmac@gmail.com>
Dominik Honnef <dominik@honnef.co>
Don Spaulding <donspauldingii@gmail.com>
ezbercih <cem.ezberci@gmail.com>
Flavio Castelli <fcastelli@suse.com>
Francisco Souza <f@souza.cc>
Frederick F. Kautz IV <fkautz@alumni.cmu.edu>
Guillaume J. Charmes <guillaume.charmes@dotcloud.com>
Hunter Blanks <hunter@twilio.com>
@@ -23,10 +25,13 @@ Jérôme Petazzoni <jerome.petazzoni@dotcloud.com>
Ken Cochrane <kencochrane@gmail.com>
Kevin J. Lynagh <kevin@keminglabs.com>
Louis Opter <kalessin@kalessin.fr>
Maxim Treskin <zerthurd@gmail.com>
Mikhail Sobolev <mss@mawhrin.net>
Nelson Chen <crazysim@gmail.com>
Niall O'Higgins <niallo@unworkable.org>
Paul Hammond <paul@paulhammond.org>
Piotr Bogdan <ppbogdan@gmail.com>
Robert Obryk <robryk@gmail.com>
Sam Alba <sam.alba@gmail.com>
Shawn Siefkas <shawn.siefkas@meredith.com>
Silas Sewell <silas@sewell.org>
@@ -35,4 +40,6 @@ Sridhar Ratnakumar <sridharr@activestate.com>
Thatcher Peskens <thatcher@dotcloud.com>
Tim Terhorst <mynamewastaken+git@gmail.com>
Troy Howard <thoward37@gmail.com>
unclejack <unclejacksons@gmail.com>
Victor Vieux <victor.vieux@dotcloud.com>
Vivek Agarwal <me@vivek.im>
+4 -1
View File
@@ -13,7 +13,10 @@ endif
GIT_COMMIT = $(shell git rev-parse --short HEAD)
GIT_STATUS = $(shell test -n "`git status --porcelain`" && echo "+CHANGES")
BUILD_OPTIONS = -ldflags "-X main.GIT_COMMIT $(GIT_COMMIT)$(GIT_STATUS)"
NO_MEMORY_LIMIT ?= 0
export NO_MEMORY_LIMIT
BUILD_OPTIONS = -ldflags "-X main.GIT_COMMIT $(GIT_COMMIT)$(GIT_STATUS) -X main.NO_MEMORY_LIMIT $(NO_MEMORY_LIMIT)"
SRC_DIR := $(GOPATH)/src
+1 -1
View File
@@ -83,7 +83,7 @@ Installing on Ubuntu 12.04 and 12.10
1. Install dependencies:
```bash
sudo apt-get install lxc wget bsdtar curl
sudo apt-get install lxc bsdtar
sudo apt-get install linux-image-extra-`uname -r`
```
+71
View File
@@ -0,0 +1,71 @@
## Spec for data volumes
Spec owner: Solomon Hykes <solomon@dotcloud.com>
Data volumes (issue #111) are a much-requested feature which trigger much discussion and debate. Below is the current authoritative spec for implementing data volumes.
This spec will be deprecated once the feature is fully implemented.
Discussion, requests, trolls, demands, offerings, threats and other forms of supplications concerning this spec should be addressed to Solomon here: https://github.com/dotcloud/docker/issues/111
### 1. Creating data volumes
At container creation, parts of a container's filesystem can be mounted as separate data volumes. Volumes are defined with the -v flag.
For example:
```bash
$ docker run -v /var/lib/postgres -v /var/log postgres /usr/bin/postgres
```
In this example, a new container is created from the 'postgres' image. At the same time, docker creates 2 new data volumes: one will be mapped to the container at /var/lib/postgres, the other at /var/log.
2 important notes:
1) Volumes don't have top-level names. At no point does the user provide a name, or is a name given to him. Volumes are identified by the path at which they are mounted inside their container.
2) The user doesn't choose the source of the volume. Docker only mounts volumes it created itself, in the same way that it only runs containers that it created itself. That is by design.
### 2. Sharing data volumes
Instead of creating its own volumes, a container can share another container's volumes. For example:
```bash
$ docker run --volumes-from $OTHER_CONTAINER_ID postgres /usr/local/bin/postgres-backup
```
In this example, a new container is created from the 'postgres' example. At the same time, docker will *re-use* the 2 data volumes created in the previous example. One volume will be mounted on the /var/lib/postgres of *both* containers, and the other will be mounted on the /var/log of both containers.
### 3. Under the hood
Docker stores volumes in /var/lib/docker/volumes. Each volume receives a globally unique ID at creation, and is stored at /var/lib/docker/volumes/ID.
At creation, volumes are attached to a single container - the source of truth for this mapping will be the container's configuration.
Mounting a volume consists of calling "mount --bind" from the volume's directory to the appropriate sub-directory of the container mountpoint. This may be done by Docker itself, or farmed out to lxc (which supports mount-binding) if possible.
### 4. Backups, transfers and other volume operations
Volumes sometimes need to be backed up, transfered between hosts, synchronized, etc. These operations typically are application-specific or site-specific, eg. rsync vs. S3 upload vs. replication vs...
Rather than attempting to implement all these scenarios directly, Docker will allow for custom implementations using an extension mechanism.
### 5. Custom volume handlers
Docker allows for arbitrary code to be executed against a container's volumes, to implement any custom action: backup, transfer, synchronization across hosts, etc.
Here's an example:
```bash
$ DB=$(docker run -d -v /var/lib/postgres -v /var/log postgres /usr/bin/postgres)
$ BACKUP_JOB=$(docker run -d --volumes-from $DB shykes/backuper /usr/local/bin/backup-postgres --s3creds=$S3CREDS)
$ docker wait $BACKUP_JOB
```
Congratulations, you just implemented a custom volume handler, using Docker's built-in ability to 1) execute arbitrary code and 2) share volumes between containers.
+57 -30
View File
@@ -18,9 +18,12 @@ import (
"unicode"
)
const VERSION = "0.1.4"
const VERSION = "0.1.5"
var GIT_COMMIT string
var (
GIT_COMMIT string
NO_MEMORY_LIMIT bool
)
func (srv *Server) Name() string {
return "docker"
@@ -79,7 +82,7 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout rcli.DockerConn, args ..
n, err := stdin.Read(char)
if n > 0 {
if char[0] == '\r' || char[0] == '\n' {
stdout.Write([]byte{'\n'})
stdout.Write([]byte{'\r', '\n'})
break
} else if char[0] == 127 || char[0] == '\b' {
if i > 0 {
@@ -99,7 +102,7 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout rcli.DockerConn, args ..
}
if err != nil {
if err != io.EOF {
fmt.Fprintf(stdout, "Read error: %v\n", err)
fmt.Fprintf(stdout, "Read error: %v\r\n", err)
}
break
}
@@ -149,7 +152,7 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout rcli.DockerConn, args ..
newAuthConfig := auth.NewAuthConfig(username, password, email, srv.runtime.root)
status, err := auth.Login(newAuthConfig)
if err != nil {
fmt.Fprintln(stdout, "Error:", err)
fmt.Fprintf(stdout, "Error: %s\r\n", err)
} else {
srv.runtime.authConfig = newAuthConfig
}
@@ -161,7 +164,7 @@ func (srv *Server) CmdLogin(stdin io.ReadCloser, stdout rcli.DockerConn, args ..
// 'docker wait': block until a container stops
func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "wait", "[OPTIONS] NAME", "Block until a container stops, then print its exit code.")
cmd := rcli.Subcmd(stdout, "wait", "CONTAINER [CONTAINER...]", "Block until a container stops, then print its exit code.")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -183,6 +186,9 @@ func (srv *Server) CmdWait(stdin io.ReadCloser, stdout io.Writer, args ...string
func (srv *Server) CmdVersion(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
fmt.Fprintf(stdout, "Version:%s\n", VERSION)
fmt.Fprintf(stdout, "Git Commit:%s\n", GIT_COMMIT)
if NO_MEMORY_LIMIT {
fmt.Fprintf(stdout, "Memory limit disabled\n")
}
return nil
}
@@ -217,7 +223,7 @@ func (srv *Server) CmdInfo(stdin io.ReadCloser, stdout io.Writer, args ...string
}
func (srv *Server) CmdStop(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "stop", "[OPTIONS] NAME", "Stop a running container")
cmd := rcli.Subcmd(stdout, "stop", "CONTAINER [CONTAINER...]", "Stop a running container")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -239,7 +245,7 @@ func (srv *Server) CmdStop(stdin io.ReadCloser, stdout io.Writer, args ...string
}
func (srv *Server) CmdRestart(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "restart", "[OPTIONS] NAME", "Restart a running container")
cmd := rcli.Subcmd(stdout, "restart", "CONTAINER [CONTAINER...]", "Restart a running container")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -261,7 +267,7 @@ func (srv *Server) CmdRestart(stdin io.ReadCloser, stdout io.Writer, args ...str
}
func (srv *Server) CmdStart(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "start", "[OPTIONS] NAME", "Start a stopped container")
cmd := rcli.Subcmd(stdout, "start", "CONTAINER [CONTAINER...]", "Start a stopped container")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -283,7 +289,7 @@ func (srv *Server) CmdStart(stdin io.ReadCloser, stdout io.Writer, args ...strin
}
func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "inspect", "[OPTIONS] CONTAINER", "Return low-level information on a container")
cmd := rcli.Subcmd(stdout, "inspect", "CONTAINER", "Return low-level information on a container")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -318,7 +324,7 @@ func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...str
}
func (srv *Server) CmdPort(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "port", "[OPTIONS] CONTAINER PRIVATE_PORT", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT")
cmd := rcli.Subcmd(stdout, "port", "CONTAINER PRIVATE_PORT", "Lookup the public-facing port which is NAT-ed to PRIVATE_PORT")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -340,9 +346,9 @@ func (srv *Server) CmdPort(stdin io.ReadCloser, stdout io.Writer, args ...string
return nil
}
// 'docker rmi NAME' removes all images with the name NAME
// 'docker rmi IMAGE' removes all images with the name IMAGE
func (srv *Server) CmdRmi(stdin io.ReadCloser, stdout io.Writer, args ...string) (err error) {
cmd := rcli.Subcmd(stdout, "rmimage", "[OPTIONS] IMAGE", "Remove an image")
cmd := rcli.Subcmd(stdout, "rmimage", "IMAGE [IMAGE...]", "Remove an image")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -351,7 +357,11 @@ func (srv *Server) CmdRmi(stdin io.ReadCloser, stdout io.Writer, args ...string)
return nil
}
for _, name := range cmd.Args() {
if err := srv.runtime.graph.Delete(name); err != nil {
img, err := srv.runtime.repositories.LookupImage(name)
if err != nil {
return err
}
if err := srv.runtime.graph.Delete(img.Id); err != nil {
return err
}
}
@@ -359,7 +369,7 @@ func (srv *Server) CmdRmi(stdin io.ReadCloser, stdout io.Writer, args ...string)
}
func (srv *Server) CmdHistory(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "history", "[OPTIONS] IMAGE", "Show the history of an image")
cmd := rcli.Subcmd(stdout, "history", "IMAGE", "Show the history of an image")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -385,10 +395,14 @@ func (srv *Server) CmdHistory(stdin io.ReadCloser, stdout io.Writer, args ...str
}
func (srv *Server) CmdRm(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "rm", "[OPTIONS] CONTAINER", "Remove a container")
cmd := rcli.Subcmd(stdout, "rm", "CONTAINER [CONTAINER...]", "Remove a container")
if err := cmd.Parse(args); err != nil {
return nil
}
if cmd.NArg() < 1 {
cmd.Usage()
return nil
}
for _, name := range cmd.Args() {
container := srv.runtime.Get(name)
if container == nil {
@@ -403,10 +417,14 @@ func (srv *Server) CmdRm(stdin io.ReadCloser, stdout io.Writer, args ...string)
// 'docker kill NAME' kills a running container
func (srv *Server) CmdKill(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "kill", "[OPTIONS] CONTAINER [CONTAINER...]", "Kill a running container")
cmd := rcli.Subcmd(stdout, "kill", "CONTAINER [CONTAINER...]", "Kill a running container")
if err := cmd.Parse(args); err != nil {
return nil
}
if cmd.NArg() < 1 {
cmd.Usage()
return nil
}
for _, name := range cmd.Args() {
container := srv.runtime.Get(name)
if container == nil {
@@ -421,17 +439,19 @@ func (srv *Server) CmdKill(stdin io.ReadCloser, stdout io.Writer, args ...string
func (srv *Server) CmdImport(stdin io.ReadCloser, stdout rcli.DockerConn, args ...string) error {
stdout.Flush()
cmd := rcli.Subcmd(stdout, "import", "[OPTIONS] URL|- [REPOSITORY [TAG]]", "Create a new filesystem image from the contents of a tarball")
cmd := rcli.Subcmd(stdout, "import", "URL|- [REPOSITORY [TAG]]", "Create a new filesystem image from the contents of a tarball")
var archive io.Reader
var resp *http.Response
if err := cmd.Parse(args); err != nil {
return nil
}
if cmd.NArg() < 1 {
cmd.Usage()
return nil
}
src := cmd.Arg(0)
if src == "" {
return fmt.Errorf("Not enough arguments")
} else if src == "-" {
if src == "-" {
archive = stdin
} else {
u, err := url.Parse(src)
@@ -569,7 +589,7 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri
}
w := tabwriter.NewWriter(stdout, 20, 1, 3, ' ', 0)
if !*quiet {
fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED\tPARENT")
fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED")
}
var allImages map[string]*Image
var err error
@@ -598,7 +618,6 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri
/* TAG */ tag,
/* ID */ TruncateId(id),
/* CREATED */ HumanDuration(time.Now().Sub(image.Created)) + " ago",
/* PARENT */ srv.runtime.repositories.ImageName(image.Parent),
} {
if idx == 0 {
w.Write([]byte(field))
@@ -621,7 +640,6 @@ func (srv *Server) CmdImages(stdin io.ReadCloser, stdout io.Writer, args ...stri
/* TAG */ "<none>",
/* ID */ TruncateId(id),
/* CREATED */ HumanDuration(time.Now().Sub(image.Created)) + " ago",
/* PARENT */ srv.runtime.repositories.ImageName(image.Parent),
} {
if idx == 0 {
w.Write([]byte(field))
@@ -647,17 +665,25 @@ func (srv *Server) CmdPs(stdin io.ReadCloser, stdout io.Writer, args ...string)
quiet := cmd.Bool("q", false, "Only display numeric IDs")
flAll := cmd.Bool("a", false, "Show all containers. Only running containers are shown by default.")
flFull := cmd.Bool("notrunc", false, "Don't truncate output")
latest := cmd.Bool("l", false, "Show only the latest created container, include non-running ones.")
nLast := cmd.Int("n", -1, "Show n last created containers, include non-running ones.")
if err := cmd.Parse(args); err != nil {
return nil
}
if *nLast == -1 && *latest {
*nLast = 1
}
w := tabwriter.NewWriter(stdout, 12, 1, 3, ' ', 0)
if !*quiet {
fmt.Fprintln(w, "ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tCOMMENT")
}
for _, container := range srv.runtime.List() {
if !container.State.Running && !*flAll {
for i, container := range srv.runtime.List() {
if !container.State.Running && !*flAll && *nLast == -1 {
continue
}
if i == *nLast {
break
}
if !*quiet {
command := fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " "))
if !*flFull {
@@ -733,13 +759,14 @@ func (srv *Server) CmdExport(stdin io.ReadCloser, stdout io.Writer, args ...stri
func (srv *Server) CmdDiff(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout,
"diff", "CONTAINER [OPTIONS]",
"diff", "CONTAINER",
"Inspect changes on a container's filesystem")
if err := cmd.Parse(args); err != nil {
return nil
}
if cmd.NArg() < 1 {
return fmt.Errorf("Not enough arguments")
cmd.Usage()
return nil
}
if container := srv.runtime.Get(cmd.Arg(0)); container == nil {
return fmt.Errorf("No such container")
@@ -756,7 +783,7 @@ func (srv *Server) CmdDiff(stdin io.ReadCloser, stdout io.Writer, args ...string
}
func (srv *Server) CmdLogs(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
cmd := rcli.Subcmd(stdout, "logs", "[OPTIONS] CONTAINER", "Fetch the logs of a container")
cmd := rcli.Subcmd(stdout, "logs", "CONTAINER", "Fetch the logs of a container")
if err := cmd.Parse(args); err != nil {
return nil
}
@@ -904,7 +931,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout rcli.DockerConn, args ...s
if err != nil {
// If container not found, try to pull it
if srv.runtime.graph.IsNotExist(err) {
fmt.Fprintf(stdout, "Image %s not found, trying to pull it from registry.\n", config.Image)
fmt.Fprintf(stdout, "Image %s not found, trying to pull it from registry.\r\n", config.Image)
if err = srv.CmdPull(stdin, stdout, config.Image); err != nil {
return err
}
+17
View File
@@ -59,6 +59,20 @@ func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error
return nil
}
func cmdWait(srv *Server, container *Container) error {
stdout, stdoutPipe := io.Pipe()
go func() {
srv.CmdWait(nil, stdoutPipe, container.Id)
}()
if _, err := bufio.NewReader(stdout).ReadString('\n'); err != nil {
return err
}
// Cleanup pipes
return closeWrap(stdout, stdoutPipe)
}
// TestRunHostname checks that 'docker run -h' correctly sets a custom hostname
func TestRunHostname(t *testing.T) {
runtime, err := newTestRuntime()
@@ -89,7 +103,9 @@ func TestRunHostname(t *testing.T) {
setTimeout(t, "CmdRun timed out", 2*time.Second, func() {
<-c
cmdWait(srv, srv.runtime.List()[0])
})
}
func TestRunExit(t *testing.T) {
@@ -129,6 +145,7 @@ func TestRunExit(t *testing.T) {
// as the process exited, CmdRun must finish and unblock. Wait for it
setTimeout(t, "Waiting for CmdRun timed out", 2*time.Second, func() {
<-c1
cmdWait(srv, container)
})
// Make sure that the client has been disconnected
+60 -21
View File
@@ -33,13 +33,14 @@ type Container struct {
network *NetworkInterface
NetworkSettings *NetworkSettings
SysInitPath string
cmd *exec.Cmd
stdout *writeBroadcaster
stderr *writeBroadcaster
stdin io.ReadCloser
stdinPipe io.WriteCloser
SysInitPath string
ResolvConfPath string
cmd *exec.Cmd
stdout *writeBroadcaster
stderr *writeBroadcaster
stdin io.ReadCloser
stdinPipe io.WriteCloser
ptyMaster io.Closer
runtime *Runtime
@@ -61,6 +62,7 @@ type Config struct {
StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
Env []string
Cmd []string
Dns []string
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
}
@@ -79,12 +81,20 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
flTty := cmd.Bool("t", false, "Allocate a pseudo-tty")
flMemory := cmd.Int64("m", 0, "Memory limit (in bytes)")
if *flMemory > 0 && NO_MEMORY_LIMIT {
fmt.Fprintf(stdout, "WARNING: This version of docker has been compiled without memory limit support. Discarding -m.")
*flMemory = 0
}
var flPorts ListOpts
cmd.Var(&flPorts, "p", "Expose a container's port to the host (use 'docker port' to see the actual mapping)")
var flEnv ListOpts
cmd.Var(&flEnv, "e", "Set environment variables")
var flDns ListOpts
cmd.Var(&flDns, "dns", "Set custom dns servers")
if err := cmd.Parse(args); err != nil {
return nil, err
}
@@ -122,6 +132,7 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
AttachStderr: flAttach.Get("stderr"),
Env: flEnv,
Cmd: runCmd,
Dns: flDns,
Image: image,
}
// When allocating stdin in attached mode, close stdin at client disconnect
@@ -355,6 +366,12 @@ func (container *Container) Start() error {
if err := container.allocateNetwork(); err != nil {
return err
}
if container.Config.Memory > 0 && NO_MEMORY_LIMIT {
log.Printf("WARNING: This version of docker has been compiled without memory limit support. Discarding the limit.")
container.Config.Memory = 0
}
if err := container.generateLXCConfig(); err != nil {
return err
}
@@ -373,21 +390,26 @@ func (container *Container) Start() error {
params = append(params, "-u", container.Config.User)
}
if container.Config.Tty {
params = append(params, "-e", "TERM=xterm")
}
// Setup environment
params = append(params,
"-e", "HOME=/",
"-e", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
)
for _, elem := range container.Config.Env {
params = append(params, "-e", elem)
}
// Program
params = append(params, "--", container.Path)
params = append(params, container.Args...)
container.cmd = exec.Command("lxc-start", params...)
// Setup environment
container.cmd.Env = append(
[]string{
"HOME=/",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
},
container.Config.Env...,
)
// Setup logging of stdout and stderr to disk
if err := container.runtime.LogToDisk(container.stdout, container.logPath("stdout")); err != nil {
return err
@@ -398,10 +420,6 @@ func (container *Container) Start() error {
var err error
if container.Config.Tty {
container.cmd.Env = append(
[]string{"TERM=xterm"},
container.cmd.Env...,
)
err = container.startPty()
} else {
err = container.start()
@@ -550,9 +568,21 @@ func (container *Container) kill() error {
if !container.State.Running || container.cmd == nil {
return nil
}
if err := container.cmd.Process.Kill(); err != nil {
return err
// Sending SIGKILL to the process via lxc
output, err := exec.Command("lxc-kill", "-n", container.Id, "9").CombinedOutput()
if err != nil {
log.Printf("error killing container %s (%s, %s)", container.Id, output, err)
}
// 2. Wait for the process to die, in last resort, try to kill the process directly
if err := container.WaitTimeout(10 * time.Second); err != nil {
log.Printf("Container %s failed to exit within 10 seconds of lxc SIGKILL - trying direct SIGKILL", container.Id)
if err := container.cmd.Process.Kill(); err != nil {
return err
}
}
// Wait for the container to be actually stopped
container.Wait()
return nil
@@ -561,6 +591,12 @@ func (container *Container) kill() error {
func (container *Container) Kill() error {
container.State.lock()
defer container.State.unlock()
if !container.State.Running {
return nil
}
if container.State.Ghost {
return fmt.Errorf("Can't kill ghost container")
}
return container.kill()
}
@@ -570,6 +606,9 @@ func (container *Container) Stop() error {
if !container.State.Running {
return nil
}
if container.State.Ghost {
return fmt.Errorf("Can't stop ghot container")
}
// 1. Send a SIGTERM
if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil {
+56
View File
@@ -324,6 +324,54 @@ func TestOutput(t *testing.T) {
}
}
func TestKillDifferentUser(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
container, err := runtime.Create(&Config{
Image: GetTestImage(runtime).Id,
Cmd: []string{"tail", "-f", "/etc/resolv.conf"},
User: "daemon",
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
if container.State.Running {
t.Errorf("Container shouldn't be running")
}
if err := container.Start(); err != nil {
t.Fatal(err)
}
// Give some time to lxc to spawn the process (setuid might take some time)
container.WaitTimeout(500 * time.Millisecond)
if !container.State.Running {
t.Errorf("Container should be running")
}
if err := container.Kill(); err != nil {
t.Fatal(err)
}
if container.State.Running {
t.Errorf("Container shouldn't be running")
}
container.Wait()
if container.State.Running {
t.Errorf("Container shouldn't be running")
}
// Try stopping twice
if err := container.Kill(); err != nil {
t.Fatal(err)
}
}
func TestKill(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
@@ -346,6 +394,10 @@ func TestKill(t *testing.T) {
if err := container.Start(); err != nil {
t.Fatal(err)
}
// Give some time to lxc to spawn the process
container.WaitTimeout(500 * time.Millisecond)
if !container.State.Running {
t.Errorf("Container should be running")
}
@@ -657,6 +709,10 @@ func TestMultipleContainers(t *testing.T) {
t.Fatal(err)
}
// Make sure they are running before trying to kill them
container1.WaitTimeout(250 * time.Millisecond)
container2.WaitTimeout(250 * time.Millisecond)
// If we are here, both containers should be running
if !container1.State.Running {
t.Fatal("Container not running")
+96
View File
@@ -0,0 +1,96 @@
package main
import (
"io"
"log"
"os"
"os/exec"
"time"
)
const DOCKER_PATH = "/home/creack/dotcloud/docker/docker/docker"
func runDaemon() (*exec.Cmd, error) {
os.Remove("/var/run/docker.pid")
cmd := exec.Command(DOCKER_PATH, "-d")
outPipe, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
errPipe, err := cmd.StderrPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
go func() {
io.Copy(os.Stdout, outPipe)
}()
go func() {
io.Copy(os.Stderr, errPipe)
}()
return cmd, nil
}
func crashTest() error {
if err := exec.Command("/bin/bash", "-c", "while true; do true; done").Start(); err != nil {
return err
}
for {
daemon, err := runDaemon()
if err != nil {
return err
}
// time.Sleep(5000 * time.Millisecond)
var stop bool
go func() error {
stop = false
for i := 0; i < 100 && !stop; i++ {
func() error {
cmd := exec.Command(DOCKER_PATH, "run", "base", "echo", "hello", "world")
log.Printf("%d", i)
outPipe, err := cmd.StdoutPipe()
if err != nil {
return err
}
inPipe, err := cmd.StdinPipe()
if err != nil {
return err
}
if err := cmd.Start(); err != nil {
return err
}
go func() {
io.Copy(os.Stdout, outPipe)
}()
// Expecting error, do not check
inPipe.Write([]byte("hello world!!!!!\n"))
go inPipe.Write([]byte("hello world!!!!!\n"))
go inPipe.Write([]byte("hello world!!!!!\n"))
inPipe.Close()
if err := cmd.Wait(); err != nil {
return err
}
outPipe.Close()
return nil
}()
}
return nil
}()
time.Sleep(20 * time.Second)
stop = true
if err := daemon.Process.Kill(); err != nil {
return err
}
}
return nil
}
func main() {
if err := crashTest(); err != nil {
log.Println(err)
}
}
+68
View File
@@ -0,0 +1,68 @@
# docker-build: build your software with docker
## Description
docker-build is a script to build docker images from source. It will be deprecated once the 'build' feature is incorporated into docker itself (See https://github.com/dotcloud/docker/issues/278)
Author: Solomon Hykes <solomon@dotcloud.com>
## Install
docker-builder requires:
1) A reasonably recent Python setup (tested on 2.7.2).
2) A running docker daemon at version 0.1.4 or more recent (http://www.docker.io/gettingstarted)
## Usage
First create a valid Changefile, which defines a sequence of changes to apply to a base image.
$ cat Changefile
# Start build from a know base image
from base:ubuntu-12.10
# Update ubuntu sources
run echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list
run apt-get update
# Install system packages
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
# Insert files from the host (./myscript must be present in the current directory)
copy myscript /usr/local/bin/myscript
Run docker-build, and pass the contents of your Changefile as standard input.
$ IMG=$(./docker-build < Changefile)
This will take a while: for each line of the changefile, docker-build will:
1. Create a new container to execute the given command or insert the given file
2. Wait for the container to complete execution
3. Commit the resulting changes as a new image
4. Use the resulting image as the input of the next step
If all the steps succeed, the result will be an image containing the combined results of each build step.
You can trace back those build steps by inspecting the image's history:
$ docker history $IMG
ID CREATED CREATED BY
1e9e2045de86 A few seconds ago /bin/sh -c cat > /usr/local/bin/myscript; chmod +x /usr/local/bin/git
77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl
77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
83e85d155451 A few seconds ago /bin/sh -c apt-get update
bfd53b36d9d3 A few seconds ago /bin/sh -c echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list
base 2 weeks ago /bin/bash
27cf78414709 2 weeks ago
Note that your build started from 'base', as instructed by your Changefile. But that base image itself seems to have been built in 2 steps - hence the extra step in the history.
You can use this build technique to create any image you want: a database, a web application, or anything else that can be build by a sequence of unix commands - in other words, anything else.
+104
View File
@@ -0,0 +1,104 @@
#!/usr/bin/env python
# docker-build is a script to build docker images from source.
# It will be deprecated once the 'build' feature is incorporated into docker itself.
# (See https://github.com/dotcloud/docker/issues/278)
#
# Author: Solomon Hykes <solomon@dotcloud.com>
# First create a valid Changefile, which defines a sequence of changes to apply to a base image.
#
# $ cat Changefile
# # Start build from a know base image
# from base:ubuntu-12.10
# # Update ubuntu sources
# run echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list
# run apt-get update
# # Install system packages
# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl
# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
# # Insert files from the host (./myscript must be present in the current directory)
# copy myscript /usr/local/bin/myscript
#
#
# Run docker-build, and pass the contents of your Changefile as standard input.
#
# $ IMG=$(./docker-build < Changefile)
#
# This will take a while: for each line of the changefile, docker-build will:
#
# 1. Create a new container to execute the given command or insert the given file
# 2. Wait for the container to complete execution
# 3. Commit the resulting changes as a new image
# 4. Use the resulting image as the input of the next step
import sys
import subprocess
import json
import hashlib
def docker(args, stdin=None):
print "# docker " + " ".join(args)
p = subprocess.Popen(["docker"] + list(args), stdin=stdin, stdout=subprocess.PIPE)
return p.stdout
def image_exists(img):
return docker(["inspect", img]).read().strip() != ""
def run_and_commit(img_in, cmd, stdin=None):
run_id = docker(["run"] + (["-i", "-a", "stdin"] if stdin else ["-d"]) + [img_in, "/bin/sh", "-c", cmd], stdin=stdin).read().rstrip()
print "---> Waiting for " + run_id
result=int(docker(["wait", run_id]).read().rstrip())
if result != 0:
print "!!! '{}' return non-zero exit code '{}'. Aborting.".format(cmd, result)
sys.exit(1)
return docker(["commit", run_id]).read().rstrip()
def insert(base, src, dst):
print "COPY {} to {} in {}".format(src, dst, base)
if dst == "":
raise Exception("Missing destination path")
stdin = file(src)
stdin.seek(0)
return run_and_commit(base, "cat > {0}; chmod +x {0}".format(dst), stdin=stdin)
def main():
base=""
steps = []
try:
for line in sys.stdin.readlines():
line = line.strip()
# Skip comments and empty lines
if line == "" or line[0] == "#":
continue
op, param = line.split(" ", 1)
if op == "from":
print "FROM " + param
base = param
steps.append(base)
elif op == "run":
print "RUN " + param
result = run_and_commit(base, param)
steps.append(result)
base = result
print "===> " + base
elif op == "copy":
src, dst = param.split(" ", 1)
result = insert(base, src, dst)
steps.append(result)
base = result
print "===> " + base
else:
print "Skipping uknown op " + op
except:
docker(["rmi"] + steps)
raise
print base
if __name__ == "__main__":
main()
+11
View File
@@ -0,0 +1,11 @@
# Start build from a know base image
from base:ubuntu-12.10
# Update ubuntu sources
run echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list
run apt-get update
# Install system packages
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl
run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
# Insert files from the host (./myscript must be present in the current directory)
copy myscript /usr/local/bin/myscript
+1 -1
View File
@@ -45,7 +45,7 @@ then
echo "Upstart script already exists."
else
echo "Creating /etc/init/dockerd.conf..."
echo "exec /usr/local/bin/docker -d" > /etc/init/dockerd.conf
echo "exec env LANG=\"en_US.UTF-8\" /usr/local/bin/docker -d" > /etc/init/dockerd.conf
fi
echo "Starting dockerd..."
-1
View File
@@ -1 +0,0 @@
../Makefile
-1
View File
@@ -1 +0,0 @@
../README.md
-5
View File
@@ -1,5 +0,0 @@
dotcloud-docker (1) precise; urgency=low
* Initial release
-- dotCloud <ops@dotcloud.com> Mon, 14 Mar 2013 04:43:21 -0700
-10
View File
@@ -1,10 +0,0 @@
description "Run docker"
start on runlevel [2345]
stop on starting rc RUNLEVEL=[016]
respawn
script
test -f /etc/default/locale && . /etc/default/locale || true
LANG=$LANG LC_ALL=$LANG /usr/bin/docker -d
end script
+51 -12
View File
@@ -2,15 +2,21 @@ package main
import (
"flag"
"fmt"
"github.com/dotcloud/docker"
"github.com/dotcloud/docker/rcli"
"github.com/dotcloud/docker/term"
"io"
"log"
"os"
"os/signal"
"syscall"
)
var GIT_COMMIT string
var (
GIT_COMMIT string
NO_MEMORY_LIMIT string
)
func main() {
if docker.SelfPath() == "/sbin/init" {
@@ -22,6 +28,7 @@ func main() {
flDaemon := flag.Bool("d", false, "Daemon mode")
flDebug := flag.Bool("D", false, "Debug mode")
bridgeName := flag.String("b", "", "Attach containers to a pre-existing network bridge")
pidfile := flag.String("p", "/var/run/docker.pid", "File containing process PID")
flag.Parse()
if *bridgeName != "" {
docker.NetworkBridgeIface = *bridgeName
@@ -32,12 +39,16 @@ func main() {
os.Setenv("DEBUG", "1")
}
docker.GIT_COMMIT = GIT_COMMIT
docker.NO_MEMORY_LIMIT = NO_MEMORY_LIMIT == "1"
if *flDaemon {
if flag.NArg() != 0 {
flag.Usage()
return
}
if err := daemon(); err != nil {
if NO_MEMORY_LIMIT == "1" {
log.Printf("WARNING: This version of docker has been compiled without memory limit support.")
}
if err := daemon(*pidfile); err != nil {
log.Fatal(err)
}
} else {
@@ -47,7 +58,43 @@ func main() {
}
}
func daemon() error {
func createPidFile(pidfile string) error {
if _, err := os.Stat(pidfile); err == nil {
return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
}
file, err := os.Create(pidfile)
if err != nil {
return err
}
defer file.Close()
_, err = fmt.Fprintf(file, "%d", os.Getpid())
return err
}
func removePidFile(pidfile string) {
if err := os.Remove(pidfile); err != nil {
log.Printf("Error removing %s: %s", pidfile, err)
}
}
func daemon(pidfile string) error {
if err := createPidFile(pidfile); err != nil {
log.Fatal(err)
}
defer removePidFile(pidfile)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill, os.Signal(syscall.SIGTERM))
go func() {
sig := <-c
log.Printf("Received signal '%v', exiting\n", sig)
removePidFile(pidfile)
os.Exit(0)
}()
service, err := docker.NewServer()
if err != nil {
return err
@@ -91,15 +138,7 @@ func runCommand(args []string) error {
}
}
} else {
service, err := docker.NewServer()
if err != nil {
return err
}
dockerConn := rcli.NewDockerLocalConn(os.Stdout)
defer dockerConn.Close()
if err := rcli.LocalCall(service, os.Stdin, dockerConn, args...); err != nil {
return err
}
return fmt.Errorf("Can't connect to docker daemon. Is 'docker -d' running on this host?")
}
return nil
}
+1
View File
@@ -16,4 +16,5 @@ Contents:
hello_world
hello_world_daemon
python_web_app
running_redis_service
running_ssh_service
@@ -0,0 +1,81 @@
:title: Running a Redis service
:description: Installing and running an redis service
:keywords: docker, example, package installation, networking, redis
.. _running_redis_service:
Create a redis service
======================
.. include:: example_header.inc
Very simple, no frills, redis service.
Open a docker container
-----------------------
.. code-block:: bash
docker run -i -t base /bin/bash
Building your image
-------------------
Update your docker container, install the redis server. Once installed, exit out of docker.
.. code-block:: bash
apt-get update
apt-get install redis-server
exit
Snapshot the installation
-------------------------
.. code-block:: bash
docker ps -a # grab the container id (this will be the last one in the list)
docker commit <container_id> <your username>/redis
Run the service
---------------
Running the service with `-d` runs the container in detached mode, leaving the
container running in the background. Use your snapshot.
.. code-block:: bash
docker run -d -p 6379 <your username>/redis /usr/bin/redis-server
Test 1
++++++
Connect to the container with the redis-cli.
.. code-block:: bash
docker ps # grab the new container id
docker inspect <container_id> # grab the ipaddress of the container
redis-cli -h <ipaddress> -p 6379
redis 10.0.3.32:6379> set docker awesome
OK
redis 10.0.3.32:6379> get docker
"awesome"
redis 10.0.3.32:6379> exit
Test 2
++++++
Connect to the host os with the redis-cli.
.. code-block:: bash
docker ps # grab the new container id
docker port <container_id> 6379 # grab the external port
ifconfig # grab the host ip address
redis-cli -h <host ipaddress> -p <external port>
redis 192.168.0.1:49153> set docker awesome
OK
redis 192.168.0.1:49153> get docker
"awesome"
redis 192.168.0.1:49153> exit
+43
View File
@@ -0,0 +1,43 @@
.. _arch_linux:
Arch Linux
==========
Installing on Arch Linux is not officially supported but can be handled via
either of the following AUR packages:
* `dotcloud-docker <https://aur.archlinux.org/packages/dotcloud-docker/>`_
* `dotcloud-docker-git <https://aur.archlinux.org/packages/dotcloud-docker-git/>`_
The dotcloud-docker package will install the latest tagged version of docker.
The dotcloud-docker-git package will build from the current master branch.
Dependencies
------------
Docker depends on several packages which will be installed automatically with
either AUR package.
* aufs3
* bridge-utils
* go
* iproute2
* linux-aufs_friendly
Installation
------------
The instructions here assume **yaourt** is installed. See
`Arch User Repository <https://wiki.archlinux.org/index.php/Arch_User_Repository#Installing_packages>`_
for information on building and installing packages from the AUR if you have not
done so before.
Keep in mind that if **linux-aufs_friendly** is not already installed that a
new kernel will be compiled and this can take quite a while.
::
yaourt -S dotcloud-docker-git
Prior to starting docker modify your bootloader to use the
**linux-aufs_friendly** kernel and reboot your system.
+1
View File
@@ -13,6 +13,7 @@ Contents:
:maxdepth: 1
ubuntulinux
archlinux
macos
windows
amazon
+1 -1
View File
@@ -111,7 +111,7 @@ func (graph *Graph) Register(layerData Archive, img *Image) error {
if graph.Exists(img.Id) {
return fmt.Errorf("Image %s already exists", img.Id)
}
tmp, err := graph.Mktemp(img.Id)
tmp, err := graph.Mktemp("")
defer os.RemoveAll(tmp)
if err != nil {
return fmt.Errorf("Mktemp failed: %s", err)
+27
View File
@@ -3,6 +3,7 @@ package docker
import (
"archive/tar"
"bytes"
"errors"
"io"
"io/ioutil"
"os"
@@ -26,6 +27,32 @@ func TestInit(t *testing.T) {
}
}
// Test that Register can be interrupted cleanly without side effects
func TestInterruptedRegister(t *testing.T) {
graph := tempGraph(t)
defer os.RemoveAll(graph.Root)
badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data
image := &Image{
Id: GenerateId(),
Comment: "testing",
Created: time.Now(),
}
go graph.Register(badArchive, image)
time.Sleep(200 * time.Millisecond)
w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling)
if _, err := graph.Get(image.Id); err == nil {
t.Fatal("Image should not exist after Register is interrupted")
}
// Registering the same image again should succeed if the first register was interrupted
goodArchive, err := fakeTar()
if err != nil {
t.Fatal(err)
}
if err := graph.Register(goodArchive, image); err != nil {
t.Fatal(err)
}
}
// FIXME: Do more extensive tests (ex: create multiple, delete, recreate;
// create multiple, check the amount of images and paths, etc..)
func TestGraphCreate(t *testing.T) {
+1
View File
@@ -0,0 +1 @@
This directory contains material helpful for hacking on docker.
+46
View File
@@ -0,0 +1,46 @@
#!/bin/sh
# This pre-commit hook will abort if a committed file doesn't pass gofmt.
# By Even Shaw <edsrzf@gmail.com>
# http://github.com/edsrzf/gofmt-git-hook
test_fmt() {
hash gofmt 2>&- || { echo >&2 "gofmt not in PATH."; exit 1; }
IFS='
'
for file in `git diff --cached --name-only --diff-filter=ACM | grep '\.go$'`
do
output=`git cat-file -p :$file | gofmt -l 2>&1`
if test $? -ne 0
then
output=`echo "$output" | sed "s,<standard input>,$file,"`
syntaxerrors="${list}${output}\n"
elif test -n "$output"
then
list="${list}${file}\n"
fi
done
exitcode=0
if test -n "$syntaxerrors"
then
echo >&2 "gofmt found syntax errors:"
printf "$syntaxerrors"
exitcode=1
fi
if test -n "$list"
then
echo >&2 "gofmt needs to format these files (run gofmt -w and git add):"
printf "$list"
exitcode=1
fi
exit $exitcode
}
case "$1" in
--about )
echo "Check Go code formatting"
;;
* )
test_fmt
;;
esac
+15 -1
View File
@@ -7,7 +7,9 @@ import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"strings"
"time"
@@ -92,7 +94,19 @@ func MountAUFS(ro []string, rw string, target string) error {
roBranches += fmt.Sprintf("%v=ro:", layer)
}
branches := fmt.Sprintf("br:%v:%v", rwBranch, roBranches)
return mount("none", target, "aufs", 0, branches)
//if error, try to load aufs kernel module
if err := mount("none", target, "aufs", 0, branches); err != nil {
log.Printf("Kernel does not support AUFS, trying to load the AUFS module with modprobe...")
if err := exec.Command("modprobe", "aufs").Run(); err != nil {
return fmt.Errorf("Unable to load the AUFS module")
}
log.Printf("...module loaded.")
if err := mount("none", target, "aufs", 0, branches); err != nil {
return fmt.Errorf("Unable to mount using aufs")
}
}
return nil
}
func (image *Image) Mount(root, rw string) error {
+1 -1
View File
@@ -78,7 +78,7 @@ lxc.mount.entry = devpts {{$ROOTFS}}/dev/pts devpts newinstance,ptmxmode=0666,no
lxc.mount.entry = {{.SysInitPath}} {{$ROOTFS}}/sbin/init none bind,ro 0 0
# In order to get a working DNS environment, mount bind (ro) the host's /etc/resolv.conf into the container
lxc.mount.entry = /etc/resolv.conf {{$ROOTFS}}/etc/resolv.conf none bind,ro 0 0
lxc.mount.entry = {{.ResolvConfPath}} {{$ROOTFS}}/etc/resolv.conf none bind,ro 0 0
# drop linux capabilities (apply mainly to the user root in the container)
+1 -1
View File
@@ -293,7 +293,7 @@ func (alloc *PortAllocator) Acquire(port int) (int, error) {
func newPortAllocator() (*PortAllocator, error) {
allocator := &PortAllocator{
inUse: make(map[int]struct{}),
inUse: make(map[int]struct{}),
fountain: make(chan int),
}
go allocator.runFountain()
+8
View File
@@ -0,0 +1,8 @@
Docker packaging
================
This directory has one subdirectory per packaging distribution.
At minimum, each of these subdirectories should contain a
README.$DISTRIBUTION explaining how to create the native
docker package and how to install it.
+35
View File
@@ -0,0 +1,35 @@
PKG_NAME=lxc-docker
DOCKER_VERSION=$(shell head -1 changelog | awk 'match($$0, /\(.+\)/) {print substr($$0, RSTART+1, RLENGTH-4)}')
GITHUB_PATH=github.com/dotcloud/docker
SOURCE_PKG=$(PKG_NAME)_$(DOCKER_VERSION).orig.tar.gz
BUILD_SRC=${CURDIR}/../../build_src
all:
# Compile docker. Used by debian dpkg-buildpackage.
cd src/${GITHUB_PATH}/docker; GOPATH=${CURDIR} go build
install:
# Used by debian dpkg-buildpackage
mkdir -p $(DESTDIR)/usr/bin
mkdir -p $(DESTDIR)/etc/init.d
install -m 0755 src/${GITHUB_PATH}/docker/docker $(DESTDIR)/usr/bin
install -o root -m 0755 debian/docker.initd $(DESTDIR)/etc/init.d/docker
debian:
# This Makefile will compile the github master branch of dotcloud/docker
# Retrieve docker project and its go structure from internet
rm -rf ${BUILD_SRC}
GOPATH=${BUILD_SRC} go get ${GITHUB_PATH}
# Add debianization
mkdir ${BUILD_SRC}/debian
cp Makefile ${BUILD_SRC}
cp -r * ${BUILD_SRC}/debian
cp ../../README.md ${BUILD_SRC}
# Cleanup
for d in `find ${BUILD_SRC} -name '.git*'`; do rm -rf $$d; done
rm -rf ${BUILD_SRC}/../${SOURCE_PKG}
rm -rf ${BUILD_SRC}/pkg
# Create docker debian files
cd ${BUILD_SRC}; tar czf ../${SOURCE_PKG} .
cd ${BUILD_SRC}; dpkg-buildpackage
rm -rf ${BUILD_SRC}
+31
View File
@@ -0,0 +1,31 @@
Docker on Debian
================
Docker has been built and tested on Wheezy. All docker functionality works
out of the box, except for memory limitation as the stock debian kernel
does not support it yet.
Building docker package
~~~~~~~~~~~~~~~~~~~~~~~
Building Dependencies: debhelper, autotools-dev and golang
Assuming you have a wheezy system up and running
# Download a fresh copy of the docker project
git clone https://github.com/dotcloud/docker.git
cd docker
# Get building dependencies
sudo apt-get update ; sudo apt-get install -y debhelper autotools-dev golang
# Make the debian package, with no memory limitation support
(cd packaging/debian; make debian NO_MEMORY_LIMIT=1)
Install docker package
~~~~~~~~~~~~~~~~~~~~~~
sudo dpkg -i lxc-docker_0.1.4-1_amd64.deb; sudo apt-get install -f -y
+22
View File
@@ -0,0 +1,22 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
$BUILDBOT_IP = '192.168.33.31'
def v10(config)
config.vm.box = 'debian'
config.vm.share_folder 'v-data', '/data/docker', File.dirname(__FILE__) + '/../..'
config.vm.network :hostonly, $BUILDBOT_IP
# Install debian packaging dependencies and create debian packages
config.vm.provision :shell, :inline => 'apt-get -qq update; apt-get install -y debhelper autotools-dev golang'
config.vm.provision :shell, :inline => 'cd /data/docker/packaging/debian; make debian'
end
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
+14
View File
@@ -0,0 +1,14 @@
lxc-docker (0.1.4-1) unstable; urgency=low
Improvements [+], Updates [*], Bug fixes [-]:
* Changed default bridge interface do 'docker0'
- Fix a race condition when running the port allocator
-- Daniel Mizyrycki <daniel@dotcloud.com> Wed, 10 Apr 2013 18:06:21 -0700
lxc-docker (0.1.0-1) unstable; urgency=low
* Initial release
-- Daniel Mizyrycki <daniel@dotcloud.com> Mon, 29 Mar 2013 18:09:55 -0700
+1
View File
@@ -0,0 +1 @@
9
+19
View File
@@ -0,0 +1,19 @@
Source: lxc-docker
Section: admin
Priority: optional
Maintainer: Daniel Mizyrycki <daniel@dotcloud.com>
Build-Depends: debhelper (>= 9),autotools-dev,golang
Standards-Version: 3.9.3
Homepage: http://github.com/dotcloud/docker
Package: lxc-docker
Architecture: linux-any
Depends: ${misc:Depends},${shlibs:Depends},lxc,bsdtar
Conflicts: docker
Description: lxc-docker is a Linux container runtime
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.
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.
+237
View File
@@ -0,0 +1,237 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: docker
Upstream-Contact: DotCloud Inc <opensource@dotcloud.com>
Source: http://github.com/dotcloud/docker
Files: *
Copyright: 2012, DotCloud Inc <opensource@dotcloud.com>
License: Apache-2.0
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2012 DotCloud Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Files: src/github.com/kr/pty/*
Copyright: Copyright (c) 2011 Keith Rarick
License: Expat
Copyright (c) 2011 Keith Rarick
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall
be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+49
View File
@@ -0,0 +1,49 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: docker
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: docker
# Description: docker daemon
### END INIT INFO
DOCKER=/usr/bin/docker
PIDFILE=/var/run/docker.pid
# Check docker is present
[ -x $DOCKER ] || log_success_msg "Docker not present"
# Get lsb functions
. /lib/lsb/init-functions
case "$1" in
start)
log_begin_msg "Starting docker..."
start-stop-daemon --start --background --exec "$DOCKER" -- -d
log_end_msg $?
;;
stop)
log_begin_msg "Stopping docker..."
docker_pid=`pgrep -f "$DOCKER -d"`
[ -n "$docker_pid" ] && kill $docker_pid
log_end_msg $?
;;
status)
docker_pid=`pgrep -f "$DOCKER -d"`
if [ -z "$docker_pid" ] ; then
echo "docker not running"
else
echo "docker running (pid $docker_pid)"
fi
;;
*)
echo "Usage: /etc/init.d/docker {start|stop|status}"
exit 1
;;
esac
exit 0
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
# Ensure cgroup is mounted
if [ -z "`/bin/egrep -e '^cgroup' /etc/fstab`" ]; then
/bin/echo 'cgroup /sys/fs/cgroup cgroup defaults 0 0' >>/etc/fstab
fi
if [ -z "`/bin/mount | /bin/egrep -e '^cgroup'`" ]; then
/bin/mount /sys/fs/cgroup
fi
# Start docker
/usr/sbin/update-rc.d docker defaults
/etc/init.d/docker start
+16
View File
@@ -0,0 +1,16 @@
Maintainer duty
===============
The Debian project specifies the role of a 'maintainer' which is the person
making the Debian package of the program. This role requires an 'sponsor' to
upload the package. As a maintainer you should follow the guide
http://www.debian.org/doc/manuals/maint-guide . Your sponsor will be there
helping you succeed.
The most relevant information to update is the changelog file:
Each new release should create a new first paragraph with new release version,
changes, and the maintainer information.
After this is done, follow README.debian to generate the actual source
packages and talk with your sponsor to upload them into the official Debian
package archive.
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
%:
dh ${@} --with autotools_dev
@@ -1,4 +1,4 @@
PKG_NAME=dotcloud-docker
PKG_NAME=lxc-docker
PKG_ARCH=amd64
PKG_VERSION=1
ROOT_PATH:=$(PWD)
+5
View File
@@ -0,0 +1,5 @@
lxc-docker (1) precise; urgency=low
* Initial release
-- dotCloud <ops@dotcloud.com> Mon, 25 Mar 2013 05:51:12 -0700
@@ -1,16 +1,15 @@
Source: dotcloud-docker
Source: lxc-docker
Section: misc
Priority: extra
Homepage: https://github.com/dotcloud/docker
Homepage: http://docker.io
Maintainer: Daniel Mizyrycki <daniel@dotcloud.com>
Build-Depends: debhelper (>= 8.0.0), git, golang
Vcs-Git: https://github.com/dotcloud/docker.git
Standards-Version: 3.9.2
Build-Depends: debhelper (>= 8.0.0), pkg-config, git, golang, libsqlite3-dev
Vcs-Git: http://github.com/dotcloud/docker.git
Standards-Version: 3.9.3
Package: dotcloud-docker
Package: lxc-docker
Architecture: amd64
Provides: dotcloud-docker
Depends: lxc, wget, bsdtar, curl
Depends: ${shlibs:Depends}, ${misc:Depends}, lxc, wget, bsdtar, curl, sqlite3
Conflicts: docker
Description: A process manager with superpowers
It encapsulates heterogeneous payloads in Standard Containers, and runs
@@ -1,5 +1,5 @@
Format: http://dep.debian.net/deps/dep5
Upstream-Name: dotcloud-docker
Upstream-Name: docker
Source: https://github.com/dotcloud/docker
Files: *
+1
View File
@@ -0,0 +1 @@
README.md
+1
View File
@@ -0,0 +1 @@
3.0 (quilt)
+3 -3
View File
@@ -138,7 +138,8 @@ func ListenAndServe(proto, addr string, service Service) error {
if err != nil {
return err
}
go func() {
go func(conn DockerConn) {
defer conn.Close()
if DEBUG_FLAG {
CLIENT_SOCKET = conn
}
@@ -146,8 +147,7 @@ func ListenAndServe(proto, addr string, service Service) error {
log.Println("Error:", err.Error())
fmt.Fprintln(conn, "Error:", err.Error())
}
conn.Close()
}()
}(conn)
}
}
return nil
+10 -10
View File
@@ -97,7 +97,7 @@ func (graph *Graph) LookupRemoteImage(imgId string, authConfig *auth.AuthConfig)
func (graph *Graph) getRemoteImage(stdout io.Writer, imgId string, authConfig *auth.AuthConfig) (*Image, Archive, error) {
client := &http.Client{}
fmt.Fprintf(stdout, "Pulling %s metadata\n", imgId)
fmt.Fprintf(stdout, "Pulling %s metadata\r\n", imgId)
// Get the Json
req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/images/"+imgId+"/json", nil)
if err != nil {
@@ -125,7 +125,7 @@ func (graph *Graph) getRemoteImage(stdout io.Writer, imgId string, authConfig *a
img.Id = imgId
// Get the layer
fmt.Fprintf(stdout, "Pulling %s fs layer\n", imgId)
fmt.Fprintf(stdout, "Pulling %s fs layer\r\n", imgId)
req, err = http.NewRequest("GET", REGISTRY_ENDPOINT+"/images/"+imgId+"/layer", nil)
if err != nil {
return nil, nil, fmt.Errorf("Error while getting from the server: %s\n", err)
@@ -164,7 +164,7 @@ func (graph *Graph) PullImage(stdout io.Writer, imgId string, authConfig *auth.A
func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, repositories *TagStore, authConfig *auth.AuthConfig) error {
client := &http.Client{}
fmt.Fprintf(stdout, "Pulling repository %s\n", remote)
fmt.Fprintf(stdout, "Pulling repository %s\r\n", remote)
var repositoryTarget string
// If we are asking for 'root' repository, lookup on the Library's registry
@@ -196,7 +196,7 @@ func (graph *Graph) PullRepository(stdout io.Writer, remote, askedTag string, re
return err
}
for tag, rev := range t {
fmt.Fprintf(stdout, "Pulling tag %s:%s\n", remote, tag)
fmt.Fprintf(stdout, "Pulling tag %s:%s\r\n", remote, tag)
if err = graph.PullImage(stdout, rev, authConfig); err != nil {
return err
}
@@ -223,7 +223,7 @@ func (graph *Graph) PushImage(stdout io.Writer, imgOrig *Image, authConfig *auth
return fmt.Errorf("Error while retreiving the path for {%s}: %s", img.Id, err)
}
fmt.Fprintf(stdout, "Pushing %s metadata\n", img.Id)
fmt.Fprintf(stdout, "Pushing %s metadata\r\n", img.Id)
// FIXME: try json with UTF8
jsonData := strings.NewReader(string(jsonRaw))
@@ -253,7 +253,7 @@ func (graph *Graph) PushImage(stdout io.Writer, imgOrig *Image, authConfig *auth
}
}
fmt.Fprintf(stdout, "Pushing %s fs layer\n", img.Id)
fmt.Fprintf(stdout, "Pushing %s fs layer\r\n", img.Id)
req2, err := http.NewRequest("PUT", REGISTRY_ENDPOINT+"/images/"+img.Id+"/layer", nil)
req2.SetBasicAuth(authConfig.Username, authConfig.Password)
res2, err := client.Do(req2)
@@ -375,15 +375,15 @@ func (graph *Graph) pushPrimitive(stdout io.Writer, remote, tag, imgId string, a
// Check if the local impage exists
img, err := graph.Get(imgId)
if err != nil {
fmt.Fprintf(stdout, "Skipping tag %s:%s: %s does not exist\n", remote, tag, imgId)
fmt.Fprintf(stdout, "Skipping tag %s:%s: %s does not exist\r\n", remote, tag, imgId)
return nil
}
fmt.Fprintf(stdout, "Pushing tag %s:%s\n", remote, tag)
fmt.Fprintf(stdout, "Pushing tag %s:%s\r\n", remote, tag)
// Push the image
if err = graph.PushImage(stdout, img, authConfig); err != nil {
return err
}
fmt.Fprintf(stdout, "Registering tag %s:%s\n", remote, tag)
fmt.Fprintf(stdout, "Registering tag %s:%s\r\n", remote, tag)
// And then the tag
if err = graph.pushTag(remote, imgId, tag, authConfig); err != nil {
return err
@@ -399,7 +399,7 @@ func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Re
return fmt.Errorf("Permission denied on repository %s\n", remote)
}
fmt.Fprintf(stdout, "Pushing repository %s (%d tags)\n", remote, len(localRepo))
fmt.Fprintf(stdout, "Pushing repository %s (%d tags)\r\n", remote, len(localRepo))
// For each image within the repo, push them
for tag, imgId := range localRepo {
if err := graph.pushPrimitive(stdout, remote, tag, imgId, authConfig); err != nil {
+33
View File
@@ -82,6 +82,7 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) {
if config.Hostname == "" {
config.Hostname = id[:12]
}
container := &Container{
// FIXME: we should generate the ID here instead of receiving it as an argument
Id: id,
@@ -100,6 +101,24 @@ func (runtime *Runtime) Create(config *Config) (*Container, error) {
if err := os.Mkdir(container.root, 0700); err != nil {
return nil, err
}
// If custom dns exists, then create a resolv.conf for the container
if len(config.Dns) > 0 {
container.ResolvConfPath = path.Join(container.root, "resolv.conf")
f, err := os.Create(container.ResolvConfPath)
if err != nil {
return nil, err
}
defer f.Close()
for _, dns := range config.Dns {
if _, err := f.Write([]byte("nameserver " + dns + "\n")); err != nil {
return nil, err
}
}
} else {
container.ResolvConfPath = "/etc/resolv.conf"
}
// Step 2: save the container json
if err := container.ToDisk(); err != nil {
return nil, err
@@ -119,6 +138,9 @@ func (runtime *Runtime) Load(id string) (*Container, error) {
if container.Id != id {
return container, fmt.Errorf("Container %s is stored at %s", container.Id, id)
}
if container.State.Running {
container.State.Ghost = true
}
if err := runtime.Register(container); err != nil {
return nil, err
}
@@ -134,6 +156,9 @@ func (runtime *Runtime) Register(container *Container) error {
return err
}
// init the wait lock
container.waitLock = make(chan struct{})
// FIXME: if the container is supposed to be running but is not, auto restart it?
// if so, then we need to restart monitor and init a new lock
// If the container is supposed to be running, make sure of it
@@ -150,6 +175,14 @@ func (runtime *Runtime) Register(container *Container) error {
}
}
}
// If the container is not running or just has been flagged not running
// then close the wait lock chan (will be reset upon start)
if !container.State.Running {
close(container.waitLock)
}
// Even if not running, we init the lock (prevents races in start/stop/kill)
container.State.initLock()
container.runtime = runtime
+4 -12
View File
@@ -12,12 +12,9 @@ import (
"time"
)
// FIXME: this is no longer needed
const testLayerPath string = "/var/lib/docker/docker-ut.tar"
const unitTestImageName string = "docker-ut"
var unitTestStoreBase string
var srv *Server
const unitTestStoreBase string = "/var/lib/docker/unit-tests"
func nuke(runtime *Runtime) error {
var wg sync.WaitGroup
@@ -49,6 +46,8 @@ func layerArchive(tarfile string) (io.Reader, error) {
}
func init() {
NO_MEMORY_LIMIT = os.Getenv("NO_MEMORY_LIMIT") == "1"
// Hack to run sys init during unit testing
if SelfPath() == "/sbin/init" {
SysInit()
@@ -61,15 +60,8 @@ func init() {
panic("docker tests needs to be run as root")
}
// Create a temp directory
root, err := ioutil.TempDir("", "docker-test")
if err != nil {
panic(err)
}
unitTestStoreBase = root
// Make it our Store root
runtime, err := NewRuntimeFromDirectory(root)
runtime, err := NewRuntimeFromDirectory(unitTestStoreBase)
if err != nil {
panic(err)
}
+4
View File
@@ -12,11 +12,15 @@ type State struct {
ExitCode int
StartedAt time.Time
l *sync.Mutex
Ghost bool
}
// String returns a human-readable description of the state
func (s *State) String() string {
if s.Running {
if s.Ghost {
return fmt.Sprintf("Ghost")
}
return fmt.Sprintf("Up %s", HumanDuration(time.Now().Sub(s.StartedAt)))
}
return fmt.Sprintf("Exit %d", s.ExitCode)
+6 -5
View File
@@ -17,8 +17,7 @@ func setupNetworking(gw string) {
if gw == "" {
return
}
cmd := exec.Command("/sbin/route", "add", "default", "gw", gw)
if err := cmd.Run(); err != nil {
if _, err := ip("route", "add", "default", "via", gw); err != nil {
log.Fatalf("Unable to set up networking: %v", err)
}
}
@@ -54,8 +53,7 @@ func changeUser(u string) {
}
// Clear environment pollution introduced by lxc-start
func cleanupEnv() {
env := os.Environ()
func cleanupEnv(env ListOpts) {
os.Clearenv()
for _, kv := range env {
parts := strings.SplitN(kv, "=", 2)
@@ -92,10 +90,13 @@ func SysInit() {
var u = flag.String("u", "", "username or uid")
var gw = flag.String("g", "", "gateway address")
var flEnv ListOpts
flag.Var(&flEnv, "e", "Set environment variables")
flag.Parse()
cleanupEnv(flEnv)
setupNetworking(*gw)
cleanupEnv()
changeUser(*u)
executeProgram(flag.Arg(0), flag.Args())
}