[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
03/04: scripts: environment: Add --container option.
From: |
David Thompson |
Subject: |
03/04: scripts: environment: Add --container option. |
Date: |
Thu, 23 Jul 2015 01:31:16 +0000 |
davexunit pushed a commit to branch wip-container
in repository guix.
commit 54b725325915886c0220578f8474d372cbec2870
Author: David Thompson <address@hidden>
Date: Fri Jun 19 08:57:44 2015 -0400
scripts: environment: Add --container option.
* guix/scripts/enviroment.scm (show-help): Show help for new option.
(%options): Add --container option.
(launch-environment, launch-environment/container): New procedures.
(guix-environment): Spawn new process in a container when requested.
* doc/guix.texi (Invoking guix environment): Document it.
---
doc/guix.texi | 49 ++++++++++++++++++++++++++++++-----------
guix/scripts/environment.scm | 49 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 83 insertions(+), 15 deletions(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index 1a56913..360ac4f 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -4294,6 +4294,18 @@ NumPy:
guix environment --ad-hoc python2-numpy python-2.7 -E python
@end example
+Sometimes it is desirable to isolate the environment as much as
+possible, for maximal purity and reproducibility. In particular, when
+using Guix on a host distro that is not GuixSD, it is desirable to
+prevent access to @file{/usr/bin} and other system-wide resources from
+the development environment. For example, the following command spawns
+a Guile REPL in a ``container'' where only the store and the current
+working directory are mounted:
+
address@hidden
+guix environment --ad-hoc --container guile --exec=guile
address@hidden example
+
The available options are summarized below.
@table @code
@@ -4359,6 +4371,15 @@ environment.
@item address@hidden
@itemx -s @var{system}
Attempt to build for @var{system}---e.g., @code{i686-linux}.
+
address@hidden --container
address@hidden -C
address@hidden container
+Run @var{command} within an isolated container. The current working
+directory outside the container is mapped to @file{/env} inside the
+container. Additionally, the spawned process runs as the current user
+outside the container, but has root privileges in the context of the
+container.
@end table
It also supports all of the common build options that @command{guix
@@ -6388,6 +6409,7 @@ This command also installs GRUB on the device specified in
@item vm
@cindex virtual machine
@cindex VM
address@hidden system vm}
Build a virtual machine that contain the operating system declared in
@var{file}, and return a script to run that virtual machine (VM).
Arguments given to the script are passed as is to QEMU.
@@ -6437,20 +6459,21 @@ using the following command:
@end example
@item container
address@hidden container
Return a script to run the operating system declared in @var{file}
-within a container. Currently, the script must be run as root in order
-to support more than a single user and group.
-
-The container shares its store with the host system.
-
-Additional file systems can be shared between the host and the container
-using the @code{--share} and @code{--expose} command-line options: the
-former specifies a directory to be shared with write access, while the
-latter provides read-only access to the shared directory.
-
-The example below creates a container in which the user's home directory
-is accessible read-only, and where the @file{/exchange} directory is a
-read-write mapping of the host's @file{$HOME/tmp}:
+within a @dfn{container}. Containers are a set of lightweight isolation
+mechanisms provided by the kernel Linux-libre. Containers are
+substantially less resource-demanding than full virtual machines since
+the kernel, shared objects, and other resources can be shared with the
+host system; this also means they provide thinner isolation. Currently,
address@hidden system container} must be run as root in order to support
+more than a single user and group.
+
+Containers share their store with the host system.
+
+As with the @code{vm} action (@pxref{guix system vm}), additional file
+systems to be shared between the host and container can be specified
+using the @option{--share} and @option{--expose} options:
@example
guix system container my-config.scm \
diff --git a/guix/scripts/environment.scm b/guix/scripts/environment.scm
index ecdbc7a..cf8af9a 100644
--- a/guix/scripts/environment.scm
+++ b/guix/scripts/environment.scm
@@ -28,6 +28,9 @@
#:use-module (guix monads)
#:use-module ((guix gexp) #:select (lower-inputs))
#:use-module (guix scripts build)
+ #:use-module (gnu build linux-container)
+ #:use-module (gnu system linux-container)
+ #:use-module (gnu system file-systems)
#:use-module (gnu packages)
#:use-module (ice-9 format)
#:use-module (ice-9 match)
@@ -122,6 +125,8 @@ shell command in that environment.\n"))
--search-paths display needed environment variable definitions"))
(display (_ "
-s, --system=SYSTEM attempt to build for SYSTEM--e.g., \"i686-linux\""))
+ (display (_ "
+ -C, --container run command within an isolated container"))
(newline)
(show-build-options-help)
(newline)
@@ -174,6 +179,9 @@ shell command in that environment.\n"))
(lambda (opt name arg result)
(alist-cons 'system arg
(alist-delete 'system result eq?))))
+ (option '(#\C "container") #f #f
+ (lambda (opt name arg result)
+ (alist-cons 'container? #t result)))
%standard-build-options))
(define (pick-all alist key)
@@ -229,6 +237,39 @@ OUTPUT) tuples, using the build options in OPTS."
(built-derivations derivations)
(return derivations))))))))
+(define (launch-environment command inputs paths pure?)
+ "Run COMMAND in a new environment containing INPUTS, using the native search
+paths defined by the list PATHS. When PURE?, pre-existing environment
+variables are cleared before setting the new ones."
+ (create-environment inputs paths pure?)
+ (system command))
+
+(define (launch-environment/container command inputs paths)
+ "Run COMMAND within a Linux container that includes INPUTS and the
+environment variables defined by PATHS, a list of native search paths."
+ ;; Bind-mount the store and the current working directory within the
+ ;; container.
+ (let* ((cwd (getcwd))
+ (mappings
+ (list (file-system-mapping
+ (source (%store-prefix))
+ (target (%store-prefix))
+ (writable? #f))
+ (file-system-mapping
+ (source cwd)
+ (target cwd)
+ (writable? #t))))
+ (file-systems
+ (append %container-file-systems
+ (map mapping->file-system mappings)))
+ (status
+ (call-with-container (map file-system->spec file-systems)
+ (lambda ()
+ (chdir cwd)
+ ;; A container's environment is already purified.
+ (launch-environment command inputs paths #f)))))
+ (status:exit-val status)))
+
;; Entry point.
(define (guix-environment . args)
(define (handle-argument arg result)
@@ -238,6 +279,7 @@ OUTPUT) tuples, using the build options in OPTS."
(let* ((opts (parse-command-line args %options (list %default-options)
#:argument-handler handle-argument))
(pure? (assoc-ref opts 'pure))
+ (container? (assoc-ref opts 'container?))
(ad-hoc? (assoc-ref opts 'ad-hoc?))
(command (assoc-ref opts 'exec))
(packages (pick-all (options/resolve-packages opts) 'package))
@@ -279,6 +321,9 @@ OUTPUT) tuples, using the build options in OPTS."
((assoc-ref opts 'search-paths)
(show-search-paths inputs paths pure?)
(return #t))
+ (container?
+ (return
+ (launch-environment/container command inputs paths)))
(else
- (create-environment inputs paths pure?)
- (return (exit (status:exit-val (system
command)))))))))))))
+ (return
+ (launch-environment command inputs paths pure?)))))))))))