Install APT packages before copying the repo contents

pull/716/head
Tim Head 2019-06-25 12:22:25 +02:00
rodzic cd809645a9
commit 10ca25d986
1 zmienionych plików z 52 dodań i 12 usunięć

Wyświetl plik

@ -114,12 +114,6 @@ WORKDIR ${REPO_DIR}
# installs. See https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html # installs. See https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
ENV PATH ${HOME}/.local/bin:${REPO_DIR}/.local/bin:${PATH} ENV PATH ${HOME}/.local/bin:${REPO_DIR}/.local/bin:${PATH}
# Copy and chown stuff. This doubles the size of the repo, because
# you can't actually copy as USER, only as root! Thanks, Docker!
USER root
COPY src/ ${REPO_DIR}
RUN chown -R ${NB_USER}:${NB_USER} ${REPO_DIR}
{% if env -%} {% if env -%}
# The rest of the environment # The rest of the environment
{% for item in env -%} {% for item in env -%}
@ -127,9 +121,22 @@ ENV {{item[0]}} {{item[1]}}
{% endfor -%} {% endfor -%}
{% endif -%} {% endif -%}
# Run pre-assemble scripts! These are instructions that depend on the content
# of the repository but don't access any files in the repository. By executing
# them before copying the repository itself we can cache these steps. For
# example installing APT packages.
{% for sd in pre_assemble_script_directives -%}
{{ sd }}
{% endfor %}
# Run assemble scripts! These will actually build the specification # Copy and chown stuff. This doubles the size of the repo, because
# in the repository into the image. # you can't actually copy as USER, only as root! Thanks, Docker!
USER root
COPY src/ ${REPO_DIR}
RUN chown -R ${NB_USER}:${NB_USER} ${REPO_DIR}
# Run assemble scripts! These will actually turn the specification
# in the repository into an image.
{% for sd in assemble_script_directives -%} {% for sd in assemble_script_directives -%}
{{ sd }} {{ sd }}
{% endfor %} {% endfor %}
@ -372,6 +379,22 @@ class BuildPack:
return [] return []
def get_preassemble_scripts(self):
"""
Ordered list of shell snippets to build an image for this repository.
A list of tuples, where the first item is a username & the
second is a single logical line of a bash script that should
be RUN as that user.
These are run before the source of the repository is copied into
the container image. These should be the scripts that depend on the
repository but do not need access to the contents.
For example the list of APT packages to install.
"""
return []
def get_assemble_scripts(self): def get_assemble_scripts(self):
""" """
Ordered list of shell script snippets to build the repo into the image. Ordered list of shell script snippets to build the repo into the image.
@ -476,6 +499,16 @@ class BuildPack:
"RUN {}".format(textwrap.dedent(script.strip("\n"))) "RUN {}".format(textwrap.dedent(script.strip("\n")))
) )
pre_assemble_script_directives = []
last_user = "root"
for user, script in self.get_preassemble_scripts():
if last_user != user:
pre_assemble_script_directives.append("USER {}".format(user))
last_user = user
pre_assemble_script_directives.append(
"RUN {}".format(textwrap.dedent(script.strip("\n")))
)
return t.render( return t.render(
packages=sorted(self.get_packages()), packages=sorted(self.get_packages()),
path=self.get_path(), path=self.get_path(),
@ -483,6 +516,7 @@ class BuildPack:
env=self.get_env(), env=self.get_env(),
labels=self.get_labels(), labels=self.get_labels(),
build_script_directives=build_script_directives, build_script_directives=build_script_directives,
pre_assemble_script_directives=pre_assemble_script_directives,
assemble_script_directives=assemble_script_directives, assemble_script_directives=assemble_script_directives,
build_script_files=self.get_build_script_files(), build_script_files=self.get_build_script_files(),
base_packages=sorted(self.get_base_packages()), base_packages=sorted(self.get_base_packages()),
@ -618,8 +652,8 @@ class BaseImage(BuildPack):
def detect(self): def detect(self):
return True return True
def get_assemble_scripts(self): def get_preassemble_scripts(self):
assemble_scripts = [] scripts = []
try: try:
with open(self.binder_path("apt.txt")) as f: with open(self.binder_path("apt.txt")) as f:
extra_apt_packages = [] extra_apt_packages = []
@ -637,7 +671,7 @@ class BaseImage(BuildPack):
) )
extra_apt_packages.append(package) extra_apt_packages.append(package)
assemble_scripts.append( scripts.append(
( (
"root", "root",
# This apt-get install is *not* quiet, since users explicitly asked for this # This apt-get install is *not* quiet, since users explicitly asked for this
@ -648,12 +682,18 @@ class BaseImage(BuildPack):
apt-get -qq clean && \ apt-get -qq clean && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
""".format( """.format(
" ".join(extra_apt_packages) " ".join(sorted(extra_apt_packages))
), ),
) )
) )
except FileNotFoundError: except FileNotFoundError:
pass pass
return scripts
def get_assemble_scripts(self):
assemble_scripts = []
if "py" in self.stencila_contexts: if "py" in self.stencila_contexts:
assemble_scripts.extend( assemble_scripts.extend(
[ [