@@ -26,6 +26,33 @@ export enum ContainerStatus {
2626const DOCKER_DEFAULT_COMMAND = 'sh'
2727const DOCKER_CONTAINER_ID_SHORT_LENGTH = 12
2828
29+ interface ContainerMount {
30+ /**
31+ * The path inside the container
32+ */
33+ destination : string
34+
35+ /**
36+ * The path on the host
37+ */
38+ source : string
39+
40+ /**
41+ * Mount options (e.g. rw/ro)
42+ */
43+ options : Array < string >
44+ }
45+
46+ /**
47+ * Convert a ContainerMount to a --volume argument that can be passed to docker
48+ * @param containerMount
49+ */
50+ function containerMountToVolumeArg ( containerMount : ContainerMount ) : Array < string > {
51+ const options = containerMount . options . join ( ',' )
52+
53+ return [ '--volume' , `${ containerMount . source } :${ containerMount . destination } :${ options } ` ]
54+ }
55+
2956/**
3057 * Parameters of a user session inside an environment
3158 */
@@ -73,6 +100,11 @@ export class SessionParameters {
73100 * will start a new container.
74101 */
75102 containerId : string = ''
103+
104+ /**
105+ * Volumes to mount inside a container
106+ */
107+ mounts : Array < ContainerMount > = [ ]
76108}
77109
78110let ENVIRONS_HOME = path . join ( home , 'envs' )
@@ -459,7 +491,7 @@ export default class Environment {
459491 private getDockerRunCommand ( sessionParameters : SessionParameters , daemonize : boolean = false ) : Array < string > {
460492 const { command, cpuShares, memoryLimit } = sessionParameters
461493 const nixLocation = nix . location ( this . name )
462- const shellArgs = [
494+ let shellArgs = [
463495 'run' , '--interactive' , '--tty' , '--rm' ,
464496 // Prepend the environment path to the PATH variable
465497 '--env' , `PATH=${ nixLocation } /bin:${ nixLocation } /sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin` ,
@@ -470,19 +502,25 @@ export default class Environment {
470502 // Apply CPU shares
471503 `--cpu-shares=${ cpuShares } ` ,
472504 // Apply memory limit
473- `--memory=${ memoryLimit } ` ,
474- // We use Alpine Linux as a base image because it is very small but has some basic
475- // shell utilities (lkike ls and uname) that are good for debugging but also sometimes
476- // required for things like R
477- 'alpine'
478- ] . concat (
479- // Command to execute in the container
480- command ? command . split ( ' ' ) : DOCKER_DEFAULT_COMMAND
481- )
505+ `--memory=${ memoryLimit } `
506+ ]
507+
508+ sessionParameters . mounts . map ( ( mount : ContainerMount ) => {
509+ const volumeArgs = containerMountToVolumeArg ( mount )
510+ shellArgs = shellArgs . concat ( volumeArgs )
511+ } )
482512
483513 if ( daemonize ) shellArgs . splice ( 1 , 0 , '-d' )
484514
485- return shellArgs
515+ // We use Alpine Linux as a base image because it is very small but has some basic
516+ // shell utilities (lkike ls and uname) that are good for debugging but also sometimes
517+ // required for things like R
518+ shellArgs . push ( 'alpine' )
519+
520+ return shellArgs . concat (
521+ // Command to execute in the container
522+ command ? command . split ( ' ' ) : DOCKER_DEFAULT_COMMAND
523+ )
486524 }
487525
488526 /**
0 commit comments