summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Courtès <ludo@gnu.org>2019-05-12 12:21:48 +0200
committerLudovic Courtès <ludo@gnu.org>2019-05-15 16:36:21 +0200
commit247649d42e60b718f3f46b2bcf72d19bf799d503 (patch)
treefac80f7fe0923c2ba21c0f86210d2d99c0669a3d
parent7ff4fde257d43760b0df53334b4df63d16491452 (diff)
vm: 'system-docker-image' provides an entry point.
This simplifies use of images created with 'guix system docker-image'. * gnu/system/vm.scm (system-docker-image)[boot-program]: New variable. [os]: Add it to the GC roots. [build]: Pass #:entry-point to 'build-docker-image'. * gnu/tests/docker.scm (run-docker-system-test): New procedure. (%test-docker-system): New variable. * doc/guix.texi (Invoking guix system): Remove GUIX_NEW_SYSTEM hack and '--entrypoint' from the example. Mention 'docker create', 'docker start', and 'docker exec'.
-rw-r--r--doc/guix.texi18
-rw-r--r--gnu/system/vm.scm18
-rw-r--r--gnu/tests/docker.scm118
3 files changed, 145 insertions, 9 deletions
diff --git a/doc/guix.texi b/doc/guix.texi
index 41ea3c314d8..ae9ad0739e9 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -24500,20 +24500,26 @@ system configuration file. You can then load the image and launch a
24500Docker container using commands like the following: 24500Docker container using commands like the following:
24501 24501
24502@example 24502@example
24503image_id="$(docker load < guix-system-docker-image.tar.gz)" 24503image_id="`docker load < guix-system-docker-image.tar.gz`"
24504docker run -e GUIX_NEW_SYSTEM=/var/guix/profiles/system \\ 24504container_id="`docker create $image_id`"
24505 --entrypoint /var/guix/profiles/system/profile/bin/guile \\ 24505docker start $container_id
24506 $image_id /var/guix/profiles/system/boot
24507@end example 24506@end example
24508 24507
24509This command starts a new Docker container from the specified image. It 24508This command starts a new Docker container from the specified image. It
24510will boot the Guix system in the usual manner, which means it will 24509will boot the Guix system in the usual manner, which means it will
24511start any services you have defined in the operating system 24510start any services you have defined in the operating system
24512configuration. Depending on what you run in the Docker container, it 24511configuration. You can get an interactive shell running in the container
24512using @command{docker exec}:
24513
24514@example
24515docker exec -ti $container_id /run/current-system/profile/bin/bash --login
24516@end example
24517
24518Depending on what you run in the Docker container, it
24513may be necessary to give the container additional permissions. For 24519may be necessary to give the container additional permissions. For
24514example, if you intend to build software using Guix inside of the Docker 24520example, if you intend to build software using Guix inside of the Docker
24515container, you may need to pass the @option{--privileged} option to 24521container, you may need to pass the @option{--privileged} option to
24516@code{docker run}. 24522@code{docker create}.
24517 24523
24518@item container 24524@item container
24519Return a script to run the operating system declared in @var{file} 24525Return a script to run the operating system declared in @var{file}
diff --git a/gnu/system/vm.scm b/gnu/system/vm.scm
index 2eeb7007935..aa378964987 100644
--- a/gnu/system/vm.scm
+++ b/gnu/system/vm.scm
@@ -482,7 +482,7 @@ system."
482 482
483(define* (system-docker-image os 483(define* (system-docker-image os
484 #:key 484 #:key
485 (name "guixsd-docker-image") 485 (name "guix-docker-image")
486 (register-closures? (has-guix-service-type? os))) 486 (register-closures? (has-guix-service-type? os)))
487 "Build a docker image. OS is the desired <operating-system>. NAME is the 487 "Build a docker image. OS is the desired <operating-system>. NAME is the
488base name to use for the output file. When REGISTER-CLOSURES? is true, 488base name to use for the output file. When REGISTER-CLOSURES? is true,
@@ -495,7 +495,19 @@ system."
495 (local-file (search-path %load-path 495 (local-file (search-path %load-path
496 "guix/store/schema.sql")))) 496 "guix/store/schema.sql"))))
497 497
498 (let ((os (containerized-operating-system os '())) 498 (define boot-program
499 ;; Program that runs the boot script of OS, which in turn starts shepherd.
500 (program-file "boot-program"
501 #~(let ((system (cadr (command-line))))
502 (setenv "GUIX_NEW_SYSTEM" system)
503 (execl #$(file-append guile-2.2 "/bin/guile")
504 "guile" "--no-auto-compile"
505 (string-append system "/boot")))))
506
507
508 (let ((os (operating-system-with-gc-roots
509 (containerized-operating-system os '())
510 (list boot-program)))
499 (name (string-append name ".tar.gz")) 511 (name (string-append name ".tar.gz"))
500 (graph "system-graph")) 512 (graph "system-graph"))
501 (define build 513 (define build
@@ -546,9 +558,11 @@ system."
546 (string-append "/xchg/" #$graph) 558 (string-append "/xchg/" #$graph)
547 read-reference-graph))) 559 read-reference-graph)))
548 #$os 560 #$os
561 #:entry-point '(#$boot-program #$os)
549 #:compressor '(#+(file-append gzip "/bin/gzip") "-9n") 562 #:compressor '(#+(file-append gzip "/bin/gzip") "-9n")
550 #:creation-time (make-time time-utc 0 1) 563 #:creation-time (make-time time-utc 0 1)
551 #:transformations `((,root-directory -> "")))))))) 564 #:transformations `((,root-directory -> ""))))))))
565
552 (expression->derivation-in-linux-vm 566 (expression->derivation-in-linux-vm
553 name build 567 name build
554 #:make-disk-image? #f 568 #:make-disk-image? #f
diff --git a/gnu/tests/docker.scm b/gnu/tests/docker.scm
index 25e172efae3..3cd3a278840 100644
--- a/gnu/tests/docker.scm
+++ b/gnu/tests/docker.scm
@@ -1,5 +1,6 @@
1;;; GNU Guix --- Functional package management for GNU 1;;; GNU Guix --- Functional package management for GNU
2;;; Copyright © 2019 Danny Milosavljevic <dannym@scratchpost.org> 2;;; Copyright © 2019 Danny Milosavljevic <dannym@scratchpost.org>
3;;; Copyright © 2019 Ludovic Courtès <ludo@gnu.org>
3;;; 4;;;
4;;; This file is part of GNU Guix. 5;;; This file is part of GNU Guix.
5;;; 6;;;
@@ -28,6 +29,7 @@
28 #:use-module (gnu services desktop) 29 #:use-module (gnu services desktop)
29 #:use-module (gnu packages bootstrap) ; %bootstrap-guile 30 #:use-module (gnu packages bootstrap) ; %bootstrap-guile
30 #:use-module (gnu packages docker) 31 #:use-module (gnu packages docker)
32 #:use-module (gnu packages guile)
31 #:use-module (guix gexp) 33 #:use-module (guix gexp)
32 #:use-module (guix grafts) 34 #:use-module (guix grafts)
33 #:use-module (guix monads) 35 #:use-module (guix monads)
@@ -38,7 +40,8 @@
38 #:use-module (guix tests) 40 #:use-module (guix tests)
39 #:use-module (guix build-system trivial) 41 #:use-module (guix build-system trivial)
40 #:use-module ((guix licenses) #:prefix license:) 42 #:use-module ((guix licenses) #:prefix license:)
41 #:export (%test-docker)) 43 #:export (%test-docker
44 %test-docker-system))
42 45
43(define %docker-os 46(define %docker-os
44 (simple-operating-system 47 (simple-operating-system
@@ -166,3 +169,116 @@ standard output device and then enters a new line.")
166 (name "docker") 169 (name "docker")
167 (description "Test Docker container of Guix.") 170 (description "Test Docker container of Guix.")
168 (value (build-tarball&run-docker-test)))) 171 (value (build-tarball&run-docker-test))))
172
173
174(define (run-docker-system-test tarball)
175 "Load DOCKER-TARBALL as Docker image and run it in a Docker container,
176inside %DOCKER-OS."
177 (define os
178 (marionette-operating-system
179 %docker-os
180 #:imported-modules '((gnu services herd)
181 (guix combinators))))
182
183 (define vm
184 (virtual-machine
185 (operating-system os)
186 ;; FIXME: Because we're using the volatile-root setup where the root file
187 ;; system is a tmpfs overlaid over a small root file system, 'docker
188 ;; load' must be able to store the whole image into memory, hence the
189 ;; huge memory requirements. We should avoid the volatile-root setup
190 ;; instead.
191 (memory-size 3000)
192 (port-forwardings '())))
193
194 (define test
195 (with-imported-modules '((gnu build marionette)
196 (guix build utils))
197 #~(begin
198 (use-modules (srfi srfi-11) (srfi srfi-64)
199 (gnu build marionette)
200 (guix build utils))
201
202 (define marionette
203 (make-marionette (list #$vm)))
204
205 (mkdir #$output)
206 (chdir #$output)
207
208 (test-begin "docker")
209
210 (test-assert "service running"
211 (marionette-eval
212 '(begin
213 (use-modules (gnu services herd))
214 (match (start-service 'dockerd)
215 (#f #f)
216 (('service response-parts ...)
217 (match (assq-ref response-parts 'running)
218 ((pid) (number? pid))))))
219 marionette))
220
221 (test-assert "load system image and run it"
222 (marionette-eval
223 `(begin
224 (define (slurp command . args)
225 ;; Return the output from COMMAND.
226 (let* ((port (apply open-pipe* OPEN_READ command args))
227 (output (read-line port))
228 (status (close-pipe port)))
229 output))
230
231 (define (docker-cli command . args)
232 ;; Run the given Docker COMMAND.
233 (apply invoke #$(file-append docker-cli "/bin/docker")
234 command args))
235
236 (define (wait-for-container-file container file)
237 ;; Wait for FILE to show up in CONTAINER.
238 (docker-cli "exec" container
239 #$(file-append guile-2.2 "/bin/guile")
240 "-c"
241 (object->string
242 `(let loop ((n 15))
243 (when (zero? n)
244 (error "file didn't show up" ,file))
245 (unless (file-exists? ,file)
246 (sleep 1)
247 (loop (- n 1)))))))
248
249 (let* ((line (slurp #$(file-append docker-cli "/bin/docker")
250 "load" "-i" #$tarball))
251 (repository&tag (string-drop line
252 (string-length
253 "Loaded image: ")))
254 (container (slurp
255 #$(file-append docker-cli "/bin/docker")
256 "create" repository&tag)))
257 (docker-cli "start" container)
258
259 ;; Wait for shepherd to be ready.
260 (wait-for-container-file container
261 "/var/run/shepherd/socket")
262
263 (docker-cli "exec" container
264 "/run/current-system/profile/bin/herd"
265 "status")
266 (slurp #$(file-append docker-cli "/bin/docker")
267 "exec" container
268 "/run/current-system/profile/bin/herd"
269 "status" "guix-daemon")))
270 marionette))
271
272 (test-end)
273 (exit (= (test-runner-fail-count (test-runner-current)) 0)))))
274
275 (gexp->derivation "docker-system-test" test))
276
277(define %test-docker-system
278 (system-test
279 (name "docker-system")
280 (description "Run a system image as produced by @command{guix system
281docker-image} inside Docker.")
282 (value (with-monad %store-monad
283 (>>= (system-docker-image (simple-operating-system))
284 run-docker-system-test)))))