diff --git a/repo2docker/app.py b/repo2docker/app.py index a47a9120..0476d997 100644 --- a/repo2docker/app.py +++ b/repo2docker/app.py @@ -19,7 +19,7 @@ import escapism from traitlets.config import Application -from traitlets import Unicode, List, default, Tuple, Dict +from traitlets import Unicode, List, default, Tuple, Dict, Int import docker from docker.utils import kwargs_from_env @@ -117,6 +117,29 @@ class Repo2Docker(Application): config=True ) + user_id = Int( + 1000, + help=""" + UID of the user to create inside the built image. + + Should be a uid that is not currently used by anything in the image. + + Might not affect Dockerfile builds. + """, + config=True + ) + + user_name = Unicode( + 'jovyan', + help=""" + Username of the user to create inside the built image. + + Should be a uid that is not currently used by anything in the image, + and should conform to the restrictions on user names for Linux. + """, + config=True + ) + def fetch(self, url, ref, checkout_path): try: for line in execute_cmd(['git', 'clone', url, checkout_path], @@ -224,6 +247,19 @@ class Repo2Docker(Application): default=[] ) + argparser.add_argument( + '--user-id', + help='User id the primary user in the image', + default=1000, + type=int + ) + + argparser.add_argument( + '--user-name', + help='User name of primary user in the image', + default='jovyan' + ) + return argparser def json_excepthook(self, etype, evalue, traceback): @@ -307,6 +343,9 @@ class Repo2Docker(Application): self.run_cmd = args.cmd + self.user_id = int(args.user_id) + self.user_name = args.user_name + if args.build_memory_limit: self.build_memory_limit = args.build_memory_limit @@ -424,9 +463,13 @@ class Repo2Docker(Application): extra=dict(phase='building')) if self.build: + build_args = { + 'NB_USER': self.user_name, + 'NB_UID': str(self.user_id) + } self.log.info('Using %s builder\n', bp.name, extra=dict(phase='building')) - for l in picked_buildpack.build(self.output_image_spec, self.build_memory_limit): + for l in picked_buildpack.build(self.output_image_spec, self.build_memory_limit, build_args): if 'stream' in l: self.log.info(l['stream'], extra=dict(phase='building')) diff --git a/repo2docker/buildpacks/base.py b/repo2docker/buildpacks/base.py index dd0a53f2..c3a914cd 100644 --- a/repo2docker/buildpacks/base.py +++ b/repo2docker/buildpacks/base.py @@ -30,8 +30,8 @@ ENV LANGUAGE en_US.UTF-8 ENV SHELL /bin/bash # Set up user -ENV NB_USER jovyan -ENV NB_UID 1000 +ARG NB_USER +ARG NB_UID ENV HOME /home/${NB_USER} RUN adduser --disabled-password \ @@ -360,7 +360,7 @@ class BuildPack(LoggingConfigurable): post_build_scripts=self.post_build_scripts, ) - def build(self, image_spec, memory_limit): + def build(self, image_spec, memory_limit, build_args): tarf = io.BytesIO() tar = tarfile.open(fileobj=tarf, mode='w') dockerfile_tarinfo = tarfile.TarInfo("Dockerfile") @@ -406,7 +406,7 @@ class BuildPack(LoggingConfigurable): fileobj=tarf, tag=image_spec, custom_context=True, - buildargs={}, + buildargs=build_args, decode=True, forcerm=True, rm=True, diff --git a/repo2docker/buildpacks/docker.py b/repo2docker/buildpacks/docker.py index 9c4994e2..c5da9c14 100644 --- a/repo2docker/buildpacks/docker.py +++ b/repo2docker/buildpacks/docker.py @@ -18,7 +18,7 @@ class DockerBuildPack(BuildPack): with open(Dockerfile) as f: return f.read() - def build(self, image_spec, memory_limit): + def build(self, image_spec, memory_limit, build_args): limits = { # Always disable memory swap for building, since mostly # nothing good can come of that. @@ -31,7 +31,7 @@ class DockerBuildPack(BuildPack): path=os.getcwd(), dockerfile=self.binder_path(self.dockerfile), tag=image_spec, - buildargs={}, + buildargs=build_args, decode=True, forcerm=True, rm=True, diff --git a/tests/volumes.py b/tests/volumes.py index 2d021a9c..5d283562 100644 --- a/tests/volumes.py +++ b/tests/volumes.py @@ -12,9 +12,12 @@ def test_volume_abspath(): """ ts = str(time.time()) with tempfile.TemporaryDirectory() as tmpdir: + username = os.getlogin() subprocess.check_call([ 'repo2docker', - '-v', '{}:/home/jovyan'.format(tmpdir), + '-v', '{}:/home/{}'.format(tmpdir, username), + '--user-id', str(os.geteuid()), + '--user-name', username, tmpdir, '--', '/bin/bash', @@ -37,6 +40,8 @@ def test_volume_relpath(): subprocess.check_call([ 'repo2docker', '-v', '.:.', + '--user-id', str(os.geteuid()), + '--user-name', os.getlogin(), tmpdir, '--', '/bin/bash',