Browse code

Merge pull request #4000 from cap10morgan/1141-merge-configs-on-commit

merge existing config when committing

Guillaume J. Charmes authored on 2014/03/13 09:49:11
Showing 3 changed files
... ...
@@ -90,7 +90,7 @@ Commands
90 90
       -v, --version=false: Print version information and quit
91 91
       --mtu=0: Set the containers network MTU; if no value is provided: default to the default route MTU or 1500 if no default route is available
92 92
 
93
-The Docker daemon is the persistent process that manages containers.  Docker uses the same binary for both the 
93
+The Docker daemon is the persistent process that manages containers.  Docker uses the same binary for both the
94 94
 daemon and client.  To run the daemon you provide the ``-d`` flag.
95 95
 
96 96
 To force Docker to use devicemapper as the storage driver, use ``docker -d -s devicemapper``.
... ...
@@ -102,10 +102,10 @@ To run the daemon with debug output, use ``docker -d -D``.
102 102
 To use lxc as the execution driver, use ``docker -d -e lxc``.
103 103
 
104 104
 The docker client will also honor the ``DOCKER_HOST`` environment variable to set
105
-the ``-H`` flag for the client.  
105
+the ``-H`` flag for the client.
106 106
 
107 107
 ::
108
- 
108
+
109 109
         docker -H tcp://0.0.0.0:4243 ps
110 110
         # or
111 111
         export DOCKER_HOST="tcp://0.0.0.0:4243"
... ...
@@ -143,7 +143,7 @@ TMPDIR and the data directory can be set like this:
143 143
 
144 144
 You can detach from the container again (and leave it running) with
145 145
 ``CTRL-c`` (for a quiet exit) or ``CTRL-\`` to get a stacktrace of
146
-the Docker client when it quits.  When you detach from the container's 
146
+the Docker client when it quits.  When you detach from the container's
147 147
 process the exit code will be returned to the client.
148 148
 
149 149
 To stop a container, use ``docker stop``.
... ...
@@ -305,7 +305,7 @@ by using the ``git://`` schema.
305 305
 
306 306
       -m, --message="": Commit message
307 307
       -a, --author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>"
308
-      --run="": Configuration to be applied when the image is launched with `docker run`.
308
+      --run="": Configuration changes to be applied when the image is launched with `docker run`.
309 309
                (ex: -run='{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')
310 310
 
311 311
 .. _cli_commit_examples:
... ...
@@ -317,14 +317,14 @@ Commit an existing container
317 317
 
318 318
 	$ sudo docker ps
319 319
 	ID                  IMAGE               COMMAND             CREATED             STATUS              PORTS
320
-	c3f279d17e0a        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours                             
321
-	197387f1b436        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours                             
320
+	c3f279d17e0a        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours
321
+	197387f1b436        ubuntu:12.04        /bin/bash           7 days ago          Up 25 hours
322 322
 	$ docker commit c3f279d17e0a  SvenDowideit/testimage:version3
323 323
 	f5283438590d
324 324
 	$ docker images | head
325 325
 	REPOSITORY                        TAG                 ID                  CREATED             VIRTUAL SIZE
326 326
 	SvenDowideit/testimage            version3            f5283438590d        16 seconds ago      335.7 MB
327
-	
327
+
328 328
 Change the command that a container runs
329 329
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
330 330
 
... ...
@@ -346,11 +346,40 @@ run ``ls /etc``.
346 346
         apt                     host.conf        lsb-base             rc2.d
347 347
         ...
348 348
 
349
+Merged configs example
350
+......................
351
+
352
+Say you have a Dockerfile like so:
353
+
354
+.. code-block:: bash
355
+
356
+        ENV MYVAR foobar
357
+        RUN apt-get install openssh
358
+        EXPOSE 22
359
+        CMD ["/usr/sbin/sshd -D"]
360
+        ...
361
+
362
+If you run that, make some changes, and then commit, Docker will merge the environment variable and exposed port configuration settings with any that you specify in the -run= option. This is a change from Docker 0.8.0 and prior where no attempt was made to preserve any existing configuration on commit.
363
+
364
+.. code-block:: bash
365
+
366
+        $ docker build -t me/foo .
367
+        $ docker run -t -i me/foo /bin/bash
368
+        foo-container$ [make changes in the container]
369
+        foo-container$ exit
370
+        $ docker commit -run='{"Cmd": ["ls"]}' [container-id] me/bar
371
+        ...
372
+
373
+The me/bar image will now have port 22 exposed, MYVAR env var set to 'foobar', and its default command will be ["ls"].
374
+
375
+Note that this is currently a shallow merge. So, for example, if you had specified a new port spec in the -run= config above, that would have clobbered the 'EXPOSE 22' setting from the parent container.
376
+
349 377
 Full -run example
350 378
 .................
351 379
 
352 380
 The ``--run`` JSON hash changes the ``Config`` section when running ``docker inspect CONTAINERID``
353
-or ``config`` when running ``docker inspect IMAGEID``.
381
+or ``config`` when running ``docker inspect IMAGEID``. Existing configuration key-values that are
382
+not overridden in the JSON hash will be merged in.
354 383
 
355 384
 (Multiline is okay within a single quote ``'``)
356 385
 
... ...
@@ -666,7 +695,7 @@ Displaying image hierarchy
666 666
 
667 667
     Usage: docker import URL|- [REPOSITORY[:TAG]]
668 668
 
669
-    Create an empty filesystem image and import the contents of the tarball 
669
+    Create an empty filesystem image and import the contents of the tarball
670 670
     (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) into it, then optionally tag it.
671 671
 
672 672
 At this time, the URL must start with ``http`` and point to a single
... ...
@@ -950,7 +979,7 @@ Running ``docker ps`` showing 2 linked containers.
950 950
 
951 951
     $ docker ps
952 952
     CONTAINER ID        IMAGE                        COMMAND                CREATED              STATUS              PORTS               NAMES
953
-    4c01db0b339c        ubuntu:12.04                 bash                   17 seconds ago       Up 16 seconds                           webapp              
953
+    4c01db0b339c        ubuntu:12.04                 bash                   17 seconds ago       Up 16 seconds                           webapp
954 954
     d7886598dbe2        crosbymichael/redis:latest   /redis-server --dir    33 minutes ago       Up 33 minutes       6379/tcp            redis,webapp/db
955 955
     fd2645e2e2b5        busybox:latest               top                    10 days ago          Ghost                                   insane_ptolemy
956 956
 
... ...
@@ -1060,7 +1089,7 @@ containers will not be deleted.
1060 1060
     Remove one or more images
1061 1061
 
1062 1062
       -f, --force=false: Force
1063
-    
1063
+
1064 1064
 Removing tagged images
1065 1065
 ~~~~~~~~~~~~~~~~~~~~~~
1066 1066
 
... ...
@@ -1139,8 +1168,8 @@ Once the container is stopped it still exists and can be started back up.  See `
1139 1139
 The ``docker run`` command can be used in combination with ``docker commit`` to
1140 1140
 :ref:`change the command that a container runs <cli_commit_examples>`.
1141 1141
 
1142
-See :ref:`port_redirection` for more detailed information about the ``--expose``, 
1143
-``-p``, ``-P`` and ``--link`` parameters, and :ref:`working_with_links_names` for 
1142
+See :ref:`port_redirection` for more detailed information about the ``--expose``,
1143
+``-p``, ``-P`` and ``--link`` parameters, and :ref:`working_with_links_names` for
1144 1144
 specific examples using ``--link``.
1145 1145
 
1146 1146
 Known Issues (run -volumes-from)
... ...
@@ -1220,8 +1249,8 @@ starting your container.
1220 1220
 
1221 1221
    $ sudo docker run -t -i -v /var/run/docker.sock:/var/run/docker.sock -v ./static-docker:/usr/bin/docker busybox sh
1222 1222
 
1223
-By bind-mounting the docker unix socket and statically linked docker binary 
1224
-(such as that provided by https://get.docker.io), you give the container 
1223
+By bind-mounting the docker unix socket and statically linked docker binary
1224
+(such as that provided by https://get.docker.io), you give the container
1225 1225
 the full access to create and manipulate the host's docker daemon.
1226 1226
 
1227 1227
 .. code-block:: bash
... ...
@@ -281,6 +281,63 @@ func TestCommit(t *testing.T) {
281 281
 	}
282 282
 }
283 283
 
284
+func TestMergeConfigOnCommit(t *testing.T) {
285
+	eng := NewTestEngine(t)
286
+	runtime := mkRuntimeFromEngine(eng, t)
287
+	defer runtime.Nuke()
288
+
289
+	container1, _, _ := mkContainer(runtime, []string{"-e", "FOO=bar", unitTestImageID, "echo test > /tmp/foo"}, t)
290
+	defer runtime.Destroy(container1)
291
+
292
+	config, _, _, err := runconfig.Parse([]string{container1.ID, "cat /tmp/foo"}, nil)
293
+	if err != nil {
294
+		t.Error(err)
295
+	}
296
+
297
+	job := eng.Job("commit", container1.ID)
298
+	job.Setenv("repo", "testrepo")
299
+	job.Setenv("tag", "testtag")
300
+	job.SetenvJson("config", config)
301
+	var newId string
302
+	job.Stdout.AddString(&newId)
303
+	if err := job.Run(); err != nil {
304
+		t.Error(err)
305
+	}
306
+
307
+	container2, _, _ := mkContainer(runtime, []string{newId}, t)
308
+	defer runtime.Destroy(container2)
309
+
310
+	job = eng.Job("inspect", container1.Name, "container")
311
+	baseContainer, _ := job.Stdout.AddEnv()
312
+	if err := job.Run(); err != nil {
313
+		t.Error(err)
314
+	}
315
+
316
+	job = eng.Job("inspect", container2.Name, "container")
317
+	commitContainer, _ := job.Stdout.AddEnv()
318
+	if err := job.Run(); err != nil {
319
+		t.Error(err)
320
+	}
321
+
322
+	baseConfig := baseContainer.GetSubEnv("Config")
323
+	commitConfig := commitContainer.GetSubEnv("Config")
324
+
325
+	if commitConfig.Get("Env") != baseConfig.Get("Env") {
326
+		t.Fatalf("Env config in committed container should be %v, was %v",
327
+			baseConfig.Get("Env"), commitConfig.Get("Env"))
328
+	}
329
+
330
+	if baseConfig.Get("Cmd") != "[\"echo test \\u003e /tmp/foo\"]" {
331
+		t.Fatalf("Cmd in base container should be [\"echo test \\u003e /tmp/foo\"], was %s",
332
+			baseConfig.Get("Cmd"))
333
+	}
334
+
335
+	if commitConfig.Get("Cmd") != "[\"cat /tmp/foo\"]" {
336
+		t.Fatalf("Cmd in committed container should be [\"cat /tmp/foo\"], was %s",
337
+			commitConfig.Get("Cmd"))
338
+	}
339
+}
340
+
284 341
 func TestRestartKillWait(t *testing.T) {
285 342
 	eng := NewTestEngine(t)
286 343
 	srv := mkServerFromEngine(eng, t)
... ...
@@ -1038,12 +1038,17 @@ func (srv *Server) ContainerCommit(job *engine.Job) engine.Status {
1038 1038
 	if container == nil {
1039 1039
 		return job.Errorf("No such container: %s", name)
1040 1040
 	}
1041
-	var config runconfig.Config
1042
-	if err := job.GetenvJson("config", &config); err != nil {
1041
+	var config = container.Config
1042
+	var newConfig runconfig.Config
1043
+	if err := job.GetenvJson("config", &newConfig); err != nil {
1043 1044
 		return job.Error(err)
1044 1045
 	}
1045 1046
 
1046
-	img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &config)
1047
+	if err := runconfig.Merge(&newConfig, config); err != nil {
1048
+		return job.Error(err)
1049
+	}
1050
+
1051
+	img, err := srv.runtime.Commit(container, job.Getenv("repo"), job.Getenv("tag"), job.Getenv("comment"), job.Getenv("author"), &newConfig)
1047 1052
 	if err != nil {
1048 1053
 		return job.Error(err)
1049 1054
 	}