Compare commits

...

19 Commits

Author SHA1 Message Date
Solomon Hykes fe0378e9b3 Rephrase changelog 2013-07-01 17:05:49 -07:00
Guillaume J. Charmes 96a1d7c645 Bump version to 0.4.8 2013-07-01 16:58:25 -07:00
Guillaume J. Charmes 79ee8b46f4 Merge pull request #1046 from dotcloud/1043-output_id_non_attach-fix
- Runtime: Make sure the ID is displayed usgin run -d
2013-07-01 16:49:43 -07:00
Victor Vieux 55a7a8b8c9 Merge pull request #1092 from lopter/master
Fix TestGetInfo when there is more than one image in the test repository
2013-07-01 16:41:01 -07:00
Victor Vieux d1d66b9c5f Merge pull request #1078 from kstaken/fix_json_error
* Remote API: Small fix in /start if empty host config
2013-07-01 16:36:58 -07:00
Louis Opter 6dacbb451f Fix TestGetInfo when there is more than one image in the test repository
See also #1089, #1072.
2013-07-01 15:06:08 -07:00
Guillaume J. Charmes ead9cefadb Merge pull request #1089 from dotcloud/multiple_test_images-fix
- Tests: Fix unit tests when there is more than one tag within the test image
2013-07-01 13:58:04 -07:00
Guillaume J. Charmes 185a2fc55e Merge pull request #1086 from crosbymichael/1008-image-entrypoint
+ Builder: Add Entrypoint to builder and container config
2013-07-01 13:33:12 -07:00
Ken Cochrane fb8fac6c60 Merge pull request #1088 from kpelykh/master
* Documentation: Update Docker Remote API client list to include Java library
2013-07-01 12:50:31 -07:00
Guillaume J. Charmes b6f288a1ce Fix unit tests when there is more than one tag within the test image 2013-07-01 11:45:45 -07:00
zettaset-kpelykh aa9bec96b1 Issue #1087 Docker Java API client -- added java to Docker Remote API Client document 2013-07-01 11:28:40 -07:00
Michael Crosby b16ff9f859 Add Entrypoint to builder and container config
By setting an entrypoint in the Dockerfile this
allows one to run an image and only pass arguments.
2013-07-01 05:34:27 -09:00
Victor Vieux 348c5c4838 Merge pull request #1085 from dotcloud/1076-doc_delete-fix
fix status code in doc
2013-07-01 06:30:21 -07:00
Victor Vieux 8dcc6a0280 fix status code in doc 2013-07-01 13:28:58 +00:00
Victor Vieux 5e029f7600 Merge pull request #1061 from proppy/fix-slices-ref
api,server: slice are already refs, no need to return ptr
2013-07-01 04:51:56 -07:00
Kimbro Staken d8d33e8b8b Adding check for content-type header 2013-06-30 10:46:09 -07:00
Solomon Hykes b37f7d49d8 Documented release process for maintainers in hack/RELEASE.md 2013-06-29 22:08:25 -07:00
Johan Euphrosine 54da339b2c api,server: slice are already refs, no need to return ptr 2013-06-28 12:41:09 -07:00
Guillaume J. Charmes bd144a64f6 Make sure the ID is displayed usgin run -d 2013-06-27 12:48:25 -07:00
18 changed files with 296 additions and 38 deletions
+5
View File
@@ -1,5 +1,10 @@
# Changelog
## 0.4.8 (2013-07-01)
+ Builder: New build operation ENTRYPOINT adds an executable entry point to the container.
- Runtime: Fix a bug which caused 'docker run -d' to no longer print the container ID.
- Tests: Fix issues in the test suite
## 0.4.7 (2013-06-28)
* Registry: easier push/pull to a custom registry
* Remote API: the progress bar updates faster when downloading and uploading large files
+5 -3
View File
@@ -535,7 +535,7 @@ func deleteImages(srv *Server, version float64, w http.ResponseWriter, r *http.R
return err
}
if imgs != nil {
if len(*imgs) != 0 {
if len(imgs) != 0 {
b, err := json.Marshal(imgs)
if err != nil {
return err
@@ -555,8 +555,10 @@ func postContainersStart(srv *Server, version float64, w http.ResponseWriter, r
// allow a nil body for backwards compatibility
if r.Body != nil {
if err := json.NewDecoder(r.Body).Decode(hostConfig); err != nil {
return err
if r.Header.Get("Content-Type") == "application/json" {
if err := json.NewDecoder(r.Body).Decode(hostConfig); err != nil {
return err
}
}
}
+45 -16
View File
@@ -112,6 +112,11 @@ func TestGetInfo(t *testing.T) {
srv := &Server{runtime: runtime}
initialImages, err := srv.runtime.graph.All()
if err != nil {
t.Fatal(err)
}
r := httptest.NewRecorder()
if err := getInfo(srv, APIVERSION, r, nil, nil); err != nil {
@@ -123,8 +128,8 @@ func TestGetInfo(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if infos.Images != 1 {
t.Errorf("Excepted images: %d, %d found", 1, infos.Images)
if infos.Images != len(initialImages) {
t.Errorf("Excepted images: %d, %d found", len(initialImages), infos.Images)
}
}
@@ -137,6 +142,11 @@ func TestGetImagesJSON(t *testing.T) {
srv := &Server{runtime: runtime}
initialImages, err := srv.Images(true, "")
if err != nil {
t.Fatal(err)
}
// all=0
req, err := http.NewRequest("GET", "/images/json?all=0", nil)
if err != nil {
@@ -154,12 +164,19 @@ func TestGetImagesJSON(t *testing.T) {
t.Fatal(err)
}
if len(images) != 1 {
t.Errorf("Excepted 1 image, %d found", len(images))
if len(images) != len(initialImages) {
t.Errorf("Excepted %d image, %d found", len(initialImages), len(images))
}
if images[0].Repository != unitTestImageName {
t.Errorf("Excepted image %s, %s found", unitTestImageName, images[0].Repository)
found := false
for _, img := range images {
if img.Repository == unitTestImageName {
found = true
break
}
}
if !found {
t.Errorf("Excepted image %s, %+v found", unitTestImageName, images)
}
r2 := httptest.NewRecorder()
@@ -179,18 +196,25 @@ func TestGetImagesJSON(t *testing.T) {
t.Fatal(err)
}
if len(images2) != 1 {
t.Errorf("Excepted 1 image, %d found", len(images2))
if len(images2) != len(initialImages) {
t.Errorf("Excepted %d image, %d found", len(initialImages), len(images2))
}
if images2[0].ID != GetTestImage(runtime).ID {
t.Errorf("Retrieved image Id differs, expected %s, received %s", GetTestImage(runtime).ID, images2[0].ID)
found = false
for _, img := range images2 {
if img.ID == GetTestImage(runtime).ID {
found = true
break
}
}
if !found {
t.Errorf("Retrieved image Id differs, expected %s, received %+v", GetTestImage(runtime).ID, images2)
}
r3 := httptest.NewRecorder()
// filter=a
req3, err := http.NewRequest("GET", "/images/json?filter=a", nil)
req3, err := http.NewRequest("GET", "/images/json?filter=aaaaaaaaaa", nil)
if err != nil {
t.Fatal(err)
}
@@ -205,7 +229,7 @@ func TestGetImagesJSON(t *testing.T) {
}
if len(images3) != 0 {
t.Errorf("Excepted 1 image, %d found", len(images3))
t.Errorf("Excepted 0 image, %d found", len(images3))
}
r4 := httptest.NewRecorder()
@@ -1310,6 +1334,11 @@ func TestDeleteImages(t *testing.T) {
srv := &Server{runtime: runtime}
initialImages, err := srv.Images(false, "")
if err != nil {
t.Fatal(err)
}
if err := srv.runtime.repositories.Set("test", "test", unitTestImageName, true); err != nil {
t.Fatal(err)
}
@@ -1319,8 +1348,8 @@ func TestDeleteImages(t *testing.T) {
t.Fatal(err)
}
if len(images) != 2 {
t.Errorf("Excepted 2 images, %d found", len(images))
if len(images) != len(initialImages)+1 {
t.Errorf("Excepted %d images, %d found", len(initialImages)+1, len(images))
}
req, err := http.NewRequest("DELETE", "/images/test:test", nil)
@@ -1348,8 +1377,8 @@ func TestDeleteImages(t *testing.T) {
t.Fatal(err)
}
if len(images) != 1 {
t.Errorf("Excepted 1 image, %d found", len(images))
if len(images) != len(initialImages) {
t.Errorf("Excepted %d image, %d found", len(initialImages), len(images))
}
/* if c := runtime.Get(container.Id); c != nil {
+13 -2
View File
@@ -50,12 +50,23 @@ func (builder *Builder) Create(config *Config) (*Container, error) {
config.Hostname = id[:12]
}
var args []string
var entrypoint string
if len(config.Entrypoint) != 0 {
entrypoint = config.Entrypoint[0]
args = append(config.Entrypoint[1:], config.Cmd...)
} else {
entrypoint = config.Cmd[0]
args = config.Cmd[1:]
}
container := &Container{
// FIXME: we should generate the ID here instead of receiving it as an argument
ID: id,
Created: time.Now(),
Path: config.Cmd[0],
Args: config.Cmd[1:], //FIXME: de-duplicate from config
Path: entrypoint,
Args: args, //FIXME: de-duplicate from config
Config: config,
Image: img.ID, // Always use the resolved image id
NetworkSettings: &NetworkSettings{},
+18 -1
View File
@@ -141,7 +141,7 @@ func (b *buildFile) CmdEnv(args string) error {
func (b *buildFile) CmdCmd(args string) error {
var cmd []string
if err := json.Unmarshal([]byte(args), &cmd); err != nil {
utils.Debugf("Error unmarshalling: %s, using /bin/sh -c", err)
utils.Debugf("Error unmarshalling: %s, setting cmd to /bin/sh -c", err)
cmd = []string{"/bin/sh", "-c", args}
}
if err := b.commit("", cmd, fmt.Sprintf("CMD %v", cmd)); err != nil {
@@ -165,6 +165,23 @@ func (b *buildFile) CmdCopy(args string) error {
return fmt.Errorf("COPY has been deprecated. Please use ADD instead")
}
func (b *buildFile) CmdEntrypoint(args string) error {
if args == "" {
return fmt.Errorf("Entrypoint cannot be empty")
}
var entrypoint []string
if err := json.Unmarshal([]byte(args), &entrypoint); err != nil {
b.config.Entrypoint = []string{"/bin/sh", "-c", args}
} else {
b.config.Entrypoint = entrypoint
}
if err := b.commit("", b.config.Cmd, fmt.Sprintf("ENTRYPOINT %s", args)); err != nil {
return err
}
return nil
}
func (b *buildFile) addRemote(container *Container, orig, dest string) error {
file, err := utils.Download(orig, ioutil.Discard)
if err != nil {
+9
View File
@@ -79,6 +79,15 @@ run [ "$(cat /somewheeeere/over/the/rainbooow/ga)" = "bu" ]
from %s
env FOO BAR
run [ "$FOO" = "BAR" ]
`,
nil,
},
{
`
from docker-ut
ENTRYPOINT /bin/echo
CMD Hello world
`,
nil,
},
+12 -2
View File
@@ -28,7 +28,7 @@ import (
"unicode"
)
const VERSION = "0.4.7"
const VERSION = "0.4.8"
var (
GITCOMMIT string
@@ -1285,9 +1285,15 @@ func (cli *DockerCli) CmdRun(args ...string) error {
return err
}
var wait chan struct{}
if !config.AttachStdout && !config.AttachStderr {
// Make this asynchrone in order to let the client write to stdin before having to read the ID
go fmt.Fprintf(cli.out, "%s\n", runResult.ID)
wait = make(chan struct{})
go func() {
defer close(wait)
fmt.Fprintf(cli.out, "%s\n", runResult.ID)
}()
}
if config.AttachStdin || config.AttachStdout || config.AttachStderr {
@@ -1316,6 +1322,10 @@ func (cli *DockerCli) CmdRun(args ...string) error {
return err
}
}
if !config.AttachStdout && !config.AttachStderr {
<-wait
}
return nil
}
+8
View File
@@ -76,6 +76,7 @@ type Config struct {
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
Volumes map[string]struct{}
VolumesFrom string
Entrypoint []string
}
type HostConfig struct {
@@ -123,6 +124,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
cmd.Var(flVolumes, "v", "Attach a data volume")
flVolumesFrom := cmd.String("volumes-from", "", "Mount volumes from the specified container")
flEntrypoint := cmd.String("entrypoint", "", "Overwrite the default entrypoint of the image")
var flBinds ListOpts
cmd.Var(&flBinds, "b", "Bind mount a volume from the host (e.g. -b /host:/container)")
@@ -153,6 +155,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
parsedArgs := cmd.Args()
runCmd := []string{}
entrypoint := []string{}
image := ""
if len(parsedArgs) >= 1 {
image = cmd.Arg(0)
@@ -160,6 +163,10 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
if len(parsedArgs) > 1 {
runCmd = parsedArgs[1:]
}
if *flEntrypoint != "" {
entrypoint = []string{*flEntrypoint}
}
config := &Config{
Hostname: *flHostname,
PortSpecs: flPorts,
@@ -177,6 +184,7 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *HostConfig,
Image: image,
Volumes: flVolumes,
VolumesFrom: *flVolumesFrom,
Entrypoint: entrypoint,
}
hostConfig := &HostConfig{
Binds: flBinds,
+26
View File
@@ -1043,6 +1043,32 @@ func TestEnv(t *testing.T) {
}
}
func TestEntrypoint(t *testing.T) {
runtime, err := newTestRuntime()
if err != nil {
t.Fatal(err)
}
defer nuke(runtime)
container, err := NewBuilder(runtime).Create(
&Config{
Image: GetTestImage(runtime).ID,
Entrypoint: []string{"/bin/echo"},
Cmd: []string{"-n", "foobar"},
},
)
if err != nil {
t.Fatal(err)
}
defer runtime.Destroy(container)
output, err := container.Output()
if err != nil {
t.Fatal(err)
}
if string(output) != "foobar" {
t.Error(string(output))
}
}
func grepFile(t *testing.T, path string, pattern string) {
f, err := os.Open(path)
if err != nil {
+3
View File
@@ -130,3 +130,6 @@ and we will add the libraries here.
| Javascript (Angular) | dockerui | https://github.com/crosbymichael/dockerui |
| **WebUI** | | |
+----------------------+----------------+--------------------------------------------+
| Java | docker-java | https://github.com/kpelykh/docker-java |
+----------------------+----------------+--------------------------------------------+
+1 -1
View File
@@ -800,7 +800,7 @@ Remove an image
{"Deleted":"53b4f83ac9"}
]
:statuscode 204: no error
:statuscode 200: no error
:statuscode 404: no such image
:statuscode 409: conflict
:statuscode 500: server error
+1
View File
@@ -26,3 +26,4 @@
-v=[]: Creates a new volume and mounts it at the specified path.
-volumes-from="": Mount all volumes from the given container.
-b=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]
-entrypoint="": Overwrite the default entrypoint set by the image.
+7
View File
@@ -153,6 +153,13 @@ of `<src>` will be written at `<dst>`.
If `<dest>` doesn't exist, it is created along with all missing directories in its path. All new
files and directories are created with mode 0700, uid and gid 0.
2.8 ENTRYPOINT
-------------
``ENTRYPOINT /bin/echo``
The `ENTRYPOINT` instruction adds an entry command that will not be overwritten when arguments are passed to docker run, unlike the behavior of `CMD`. This allows arguments to be passed to the entrypoint. i.e. `docker run <image> -d` will pass the "-d" argument to the entrypoint.
3. Dockerfile Examples
======================
+119
View File
@@ -0,0 +1,119 @@
## A maintainer's guide to releasing Docker
So you're in charge of a docker release? Cool. Here's what to do.
If your experience deviates from this document, please document the changes to keep it
up-to-date.
### 1. Pull from master and create a release branch
```bash
$ git checkout master
$ git pull
$ git checkout -b bump_$VERSION
```
### 2. Update CHANGELOG.md
You can run this command for reference:
```bash
LAST_VERSION=$(git tag | grep -E "v[0-9\.]+$" | sort -nr | head -n 1)
git log $LAST_VERSION..HEAD
```
Each change should be formatted as ```BULLET CATEGORY: DESCRIPTION```
* BULLET is either ```-```, ```+``` or ```*```, to indicate a bugfix,
new feature or upgrade, respectively.
* CATEGORY should describe which part of the project is affected.
Valid categories are:
* Runtime
* Remote API
* Builder
* Documentation
* Hack
* DESCRIPTION: a concise description of the change that is relevant to the end-user,
using the present tense.
Changes should be described in terms of how they affect the user, for example "new feature
X which allows Y", "fixed bug which caused X", "increased performance of Y".
EXAMPLES:
```
+ Builder: 'docker build -t FOO' applies the tag FOO to the newly built container.
* Runtime: improve detection of kernel version
- Remote API: fix a bug in the optional unix socket transport
```
### 3. Change VERSION in commands.go
### 4. Run all tests
### 5. Commit and create a pull request
```bash
$ git add commands.go CHANGELOG.md
$ git commit -m "Bump version to $VERSION"
$ git push origin bump_$VERSION
```
### 6. Get 2 other maintainers to validate the pull request
### 7. Merge the pull request and apply tags
```bash
$ git checkout master
$ git merge bump_$VERSION
$ git tag -a v$VERSION # Don't forget the v!
$ git tag -f -a latest
$ git push
$ git push --tags
```
### 8. Publish binaries
To run this you will need access to the release credentials.
Get them from [the infrastructure maintainers](https://github.com/dotcloud/docker/blob/master/hack/infrastructure/MAINTAINERS).
```bash
$ RELEASE_IMAGE=image_provided_by_infrastructure_maintainers
$ BUILD=$(docker run -d -e RELEASE_PPA=0 $RELEASE_IMAGE)
```
This will do 2 things:
* It will build and upload the binaries on http://get.docker.io
* It will *test* the release on our Ubuntu PPA (a PPA is a community repository for ubuntu packages)
Wait for the build to complete.
```bash
$ docker wait $BUILD # This should print 0. If it doesn't, your build failed.
```
Check that the output looks OK. Here's an example of a correct output:
```bash
$ docker logs 2>&1 b4e7c8299d73 | grep -e 'Public URL' -e 'Successfully uploaded'
Public URL of the object is: http://get.docker.io.s3.amazonaws.com/builds/Linux/x86_64/docker-v0.4.7.tgz
Public URL of the object is: http://get.docker.io.s3.amazonaws.com/builds/Linux/x86_64/docker-latest.tgz
Successfully uploaded packages.
```
If you don't see 3 lines similar to this, something might be wrong. Check the full logs and try again.
### 9. Publish Ubuntu packages
If everything went well in the previous step, you can finalize the release by submitting the Ubuntu packages.
```bash
$ RELEASE_IMAGE=image_provided_by_infrastructure_maintainers
$ docker run -e RELEASE_PPA=1 $RELEASE_IMAGE
```
If that goes well, congratulations! You're done.
-1
View File
@@ -97,7 +97,6 @@ func init() {
if err := srv.ImagePull(unitTestImageName, "", "", os.Stdout, utils.NewStreamFormatter(false), nil); err != nil {
panic(err)
}
// Spawn a Daemon
go func() {
if err := ListenAndServe(testDaemonProto, testDaemonAddr, srv, os.Getenv("DEBUG") != ""); err != nil {
+5 -5
View File
@@ -912,7 +912,7 @@ func (srv *Server) deleteImageParents(img *Image, imgs *[]APIRmi) error {
return nil
}
func (srv *Server) deleteImage(img *Image, repoName, tag string) (*[]APIRmi, error) {
func (srv *Server) deleteImage(img *Image, repoName, tag string) ([]APIRmi, error) {
//Untag the current image
var imgs []APIRmi
tagDeleted, err := srv.runtime.repositories.Delete(repoName, tag)
@@ -925,18 +925,18 @@ func (srv *Server) deleteImage(img *Image, repoName, tag string) (*[]APIRmi, err
if len(srv.runtime.repositories.ByID()[img.ID]) == 0 {
if err := srv.deleteImageAndChildren(img.ID, &imgs); err != nil {
if err != ErrImageReferenced {
return &imgs, err
return imgs, err
}
} else if err := srv.deleteImageParents(img, &imgs); err != nil {
if err != ErrImageReferenced {
return &imgs, err
return imgs, err
}
}
}
return &imgs, nil
return imgs, nil
}
func (srv *Server) ImageDelete(name string, autoPrune bool) (*[]APIRmi, error) {
func (srv *Server) ImageDelete(name string, autoPrune bool) ([]APIRmi, error) {
img, err := srv.runtime.repositories.LookupImage(name)
if err != nil {
return nil, fmt.Errorf("No such image: %s", name)
+11 -6
View File
@@ -13,6 +13,11 @@ func TestContainerTagImageDelete(t *testing.T) {
srv := &Server{runtime: runtime}
initialImages, err := srv.Images(false, "")
if err != nil {
t.Fatal(err)
}
if err := srv.runtime.repositories.Set("utest", "tag1", unitTestImageName, false); err != nil {
t.Fatal(err)
}
@@ -25,8 +30,8 @@ func TestContainerTagImageDelete(t *testing.T) {
t.Fatal(err)
}
if len(images) != 3 {
t.Errorf("Excepted 3 images, %d found", len(images))
if len(images) != len(initialImages)+2 {
t.Errorf("Excepted %d images, %d found", len(initialImages)+2, len(images))
}
if _, err := srv.ImageDelete("utest/docker:tag2", true); err != nil {
@@ -38,8 +43,8 @@ func TestContainerTagImageDelete(t *testing.T) {
t.Fatal(err)
}
if len(images) != 2 {
t.Errorf("Excepted 2 images, %d found", len(images))
if len(images) != len(initialImages)+1 {
t.Errorf("Excepted %d images, %d found", len(initialImages)+1, len(images))
}
if _, err := srv.ImageDelete("utest:tag1", true); err != nil {
@@ -51,8 +56,8 @@ func TestContainerTagImageDelete(t *testing.T) {
t.Fatal(err)
}
if len(images) != 1 {
t.Errorf("Excepted 1 image, %d found", len(images))
if len(images) != len(initialImages) {
t.Errorf("Excepted %d image, %d found", len(initialImages), len(images))
}
}
+8 -1
View File
@@ -44,7 +44,11 @@ func CompareConfig(a, b *Config) bool {
return false
}
}
for i := 0; i < len(a.Entrypoint); i++ {
if a.Entrypoint[i] != b.Entrypoint[i] {
return false
}
}
return true
}
@@ -85,4 +89,7 @@ func MergeConfig(userConf, imageConf *Config) {
if userConf.Dns == nil || len(userConf.Dns) == 0 {
userConf.Dns = imageConf.Dns
}
if userConf.Entrypoint == nil || len(userConf.Entrypoint) == 0 {
userConf.Entrypoint = imageConf.Entrypoint
}
}