Merge pull request #6787 from vieux/pause_commit2

Pause/freeze containers during commit
This commit is contained in:
Victor Vieux 2014-07-01 10:11:18 -07:00
commit cdc62c778f
12 changed files with 66 additions and 9 deletions

View file

@ -1538,6 +1538,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
func (cli *DockerCli) CmdCommit(args ...string) error {
cmd := cli.Subcmd("commit", "[OPTIONS] CONTAINER [REPOSITORY[:TAG]]", "Create a new image from a container's changes")
flPause := cmd.Bool([]string{"p", "-pause"}, true, "Pause container during commit")
flComment := cmd.String([]string{"m", "-message"}, "", "Commit message")
flAuthor := cmd.String([]string{"a", "#author", "-author"}, "", "Author (eg. \"John Hannibal Smith <hannibal@a-team.com>\")")
// FIXME: --run is deprecated, it will be replaced with inline Dockerfile commands.
@ -1569,6 +1570,11 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
v.Set("tag", tag)
v.Set("comment", *flComment)
v.Set("author", *flAuthor)
if *flPause != true {
v.Set("pause", "0")
}
var (
config *runconfig.Config
env engine.Env

View file

@ -11,7 +11,7 @@ import (
)
const (
APIVERSION version.Version = "1.12"
APIVERSION version.Version = "1.13"
DEFAULTHTTPHOST = "127.0.0.1"
DEFAULTUNIXSOCKET = "/var/run/docker.sock"
)

View file

@ -439,6 +439,12 @@ func postCommit(eng *engine.Engine, version version.Version, w http.ResponseWrit
utils.Errorf("%s", err)
}
if r.FormValue("pause") == "" && version.GreaterThanOrEqualTo("1.13") {
job.Setenv("pause", "1")
} else {
job.Setenv("pause", r.FormValue("pause"))
}
job.Setenv("repo", r.Form.Get("repo"))
job.Setenv("tag", r.Form.Get("tag"))
job.Setenv("author", r.Form.Get("author"))

View file

@ -620,8 +620,12 @@ func (daemon *Daemon) createRootfs(container *Container, img *image.Image) error
// Commit creates a new filesystem image from the current state of a container.
// The image can optionally be tagged into a repository
func (daemon *Daemon) Commit(container *Container, repository, tag, comment, author string, config *runconfig.Config) (*image.Image, error) {
// FIXME: freeze the container before copying it to avoid data corruption?
func (daemon *Daemon) Commit(container *Container, repository, tag, comment, author string, pause bool, config *runconfig.Config) (*image.Image, error) {
if pause {
container.Pause()
defer container.Unpause()
}
if err := container.Mount(); err != nil {
return nil, err
}

View file

@ -19,6 +19,9 @@ Using an existing container's name or ID you can create a new image.
**-m, --message**=""
Commit message
**-p, --pause**=true
Pause container during commit
# EXAMPLES
## Creating a new image from an existing container

View file

@ -49,6 +49,11 @@ daemon is configured to listen on.
**New!**
`start` and `stop` will now return 304 if the container's status is not modified
`POST /commit`
**New!**
Added a `pause` parameter (default `true`) to pause the container during commit
## v1.12
### Full Documentation

View file

@ -337,6 +337,7 @@ schema.
-a, --author="" Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
-m, --message="" Commit message
-p, --pause=true Pause container during commit
It can be useful to commit a container's file changes or settings into a
new image. This allows you debug a container by running an interactive
@ -344,6 +345,11 @@ shell, or to export a working dataset to another server. Generally, it
is better to use Dockerfiles to manage your images in a documented and
maintainable way.
By default, the container being committed and its processes will be paused
while the image is committed. This reduces the likelihood of
encountering data corruption during the process of creating the commit.
If this behavior is undesired, set the 'p' option to false.
### Commit an existing container
$ sudo docker ps

View file

@ -34,6 +34,33 @@ func TestCommitAfterContainerIsDone(t *testing.T) {
logDone("commit - echo foo and commit the image")
}
func TestCommitWithoutPause(t *testing.T) {
runCmd := exec.Command(dockerBinary, "run", "-i", "-a", "stdin", "busybox", "echo", "foo")
out, _, _, err := runCommandWithStdoutStderr(runCmd)
errorOut(err, t, fmt.Sprintf("failed to run container: %v %v", out, err))
cleanedContainerID := stripTrailingCharacters(out)
waitCmd := exec.Command(dockerBinary, "wait", cleanedContainerID)
_, _, err = runCommandWithOutput(waitCmd)
errorOut(err, t, fmt.Sprintf("error thrown while waiting for container: %s", out))
commitCmd := exec.Command(dockerBinary, "commit", "-p=false", cleanedContainerID)
out, _, err = runCommandWithOutput(commitCmd)
errorOut(err, t, fmt.Sprintf("failed to commit container to image: %v %v", out, err))
cleanedImageID := stripTrailingCharacters(out)
inspectCmd := exec.Command(dockerBinary, "inspect", cleanedImageID)
out, _, err = runCommandWithOutput(inspectCmd)
errorOut(err, t, fmt.Sprintf("failed to inspect image: %v %v", out, err))
deleteContainer(cleanedContainerID)
deleteImages(cleanedImageID)
logDone("commit - echo foo and commit the image with --pause=false")
}
func TestCommitNewFile(t *testing.T) {
cmd := exec.Command(dockerBinary, "run", "--name", "commiter", "busybox", "/bin/sh", "-c", "echo koye > /foo")
if _, err := runCommand(cmd); err != nil {

View file

@ -421,7 +421,7 @@ func TestCopyVolumeUidGid(t *testing.T) {
t.Errorf("Container shouldn't be running")
}
img, err := r.Commit(container1, "", "", "unit test commited image", "", nil)
img, err := r.Commit(container1, "", "", "unit test commited image", "", true, nil)
if err != nil {
t.Error(err)
}
@ -447,7 +447,7 @@ func TestCopyVolumeUidGid(t *testing.T) {
t.Errorf("Container shouldn't be running")
}
img2, err := r.Commit(container2, "", "", "unit test commited image", "", nil)
img2, err := r.Commit(container2, "", "", "unit test commited image", "", true, nil)
if err != nil {
t.Error(err)
}
@ -481,7 +481,7 @@ func TestCopyVolumeContent(t *testing.T) {
t.Errorf("Container shouldn't be running")
}
img, err := r.Commit(container1, "", "", "unit test commited image", "", nil)
img, err := r.Commit(container1, "", "", "unit test commited image", "", true, nil)
if err != nil {
t.Error(err)
}

View file

@ -334,7 +334,7 @@ func TestDaemonCreate(t *testing.T) {
}
container, _, err = daemon.Create(config, "")
_, err = daemon.Commit(container, "testrepo", "testtag", "", "", config)
_, err = daemon.Commit(container, "testrepo", "testtag", "", "", true, config)
if err != nil {
t.Error(err)
}

View file

@ -752,7 +752,7 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
autoConfig := *b.config
autoConfig.Cmd = autoCmd
// Commit the container
image, err := b.daemon.Commit(container, "", "", "", b.maintainer, &autoConfig)
image, err := b.daemon.Commit(container, "", "", "", b.maintainer, true, &autoConfig)
if err != nil {
return err
}

View file

@ -1038,7 +1038,7 @@ func (srv *Server) ContainerCommit(job *engine.Job) engine.Status {
return job.Error(err)
}
img, err := srv.daemon.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &newConfig)
img, err := srv.daemon.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), job.GetenvBool("pause"), &newConfig)
if err != nil {
return job.Error(err)
}