Allow passing in uid and username of user built into image

This allows volumes to properly respect the uid of the user
from the host. Much easier than using user namespaces
pull/172/head
yuvipanda 2017-12-19 12:46:22 -08:00
rodzic b5a6b11b8b
commit 8f36572770
4 zmienionych plików z 57 dodań i 9 usunięć

Wyświetl plik

@ -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'))

Wyświetl plik

@ -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,

Wyświetl plik

@ -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,

Wyświetl plik

@ -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',