diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2019-05-12 12:21:48 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2019-05-15 16:36:21 +0200 |
| commit | 247649d42e60b718f3f46b2bcf72d19bf799d503 (patch) | |
| tree | fac80f7fe0923c2ba21c0f86210d2d99c0669a3d | |
| parent | 7ff4fde257d43760b0df53334b4df63d16491452 (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.texi | 18 | ||||
| -rw-r--r-- | gnu/system/vm.scm | 18 | ||||
| -rw-r--r-- | gnu/tests/docker.scm | 118 |
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 | |||
| 24500 | Docker container using commands like the following: | 24500 | Docker container using commands like the following: |
| 24501 | 24501 | ||
| 24502 | @example | 24502 | @example |
| 24503 | image_id="$(docker load < guix-system-docker-image.tar.gz)" | 24503 | image_id="`docker load < guix-system-docker-image.tar.gz`" |
| 24504 | docker run -e GUIX_NEW_SYSTEM=/var/guix/profiles/system \\ | 24504 | container_id="`docker create $image_id`" |
| 24505 | --entrypoint /var/guix/profiles/system/profile/bin/guile \\ | 24505 | docker start $container_id |
| 24506 | $image_id /var/guix/profiles/system/boot | ||
| 24507 | @end example | 24506 | @end example |
| 24508 | 24507 | ||
| 24509 | This command starts a new Docker container from the specified image. It | 24508 | This command starts a new Docker container from the specified image. It |
| 24510 | will boot the Guix system in the usual manner, which means it will | 24509 | will boot the Guix system in the usual manner, which means it will |
| 24511 | start any services you have defined in the operating system | 24510 | start any services you have defined in the operating system |
| 24512 | configuration. Depending on what you run in the Docker container, it | 24511 | configuration. You can get an interactive shell running in the container |
| 24512 | using @command{docker exec}: | ||
| 24513 | |||
| 24514 | @example | ||
| 24515 | docker exec -ti $container_id /run/current-system/profile/bin/bash --login | ||
| 24516 | @end example | ||
| 24517 | |||
| 24518 | Depending on what you run in the Docker container, it | ||
| 24513 | may be necessary to give the container additional permissions. For | 24519 | may be necessary to give the container additional permissions. For |
| 24514 | example, if you intend to build software using Guix inside of the Docker | 24520 | example, if you intend to build software using Guix inside of the Docker |
| 24515 | container, you may need to pass the @option{--privileged} option to | 24521 | container, 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 |
| 24519 | Return a script to run the operating system declared in @var{file} | 24525 | Return 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 |
| 488 | base name to use for the output file. When REGISTER-CLOSURES? is true, | 488 | base 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, | ||
| 176 | inside %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 | ||
| 281 | docker-image} inside Docker.") | ||
| 282 | (value (with-monad %store-monad | ||
| 283 | (>>= (system-docker-image (simple-operating-system)) | ||
| 284 | run-docker-system-test))))) | ||
