aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Mark <[email protected]>2021-01-13 09:48:17 -0800
committerGravatar GitHub <[email protected]>2021-01-13 09:48:17 -0800
commit5462af698df667a5c78237c6a73e1b74bdf79c7f (patch)
tree5f5fb38472fca3d267ccf6eb56338f036c42e6da
parentForce extant packages to install to the user site too during deployment (diff)
parentCI: don't do a user install for pre-commit (diff)
Merge PR #90 - fix caching of exposed packages
-rw-r--r--.github/workflows/lint-test-build-push.yaml3
-rw-r--r--Dockerfile29
-rw-r--r--README.md10
-rw-r--r--deployment.yaml3
4 files changed, 23 insertions, 22 deletions
diff --git a/.github/workflows/lint-test-build-push.yaml b/.github/workflows/lint-test-build-push.yaml
index 5aa2180..700fba9 100644
--- a/.github/workflows/lint-test-build-push.yaml
+++ b/.github/workflows/lint-test-build-push.yaml
@@ -108,11 +108,12 @@ jobs:
docker exec snekbox_test /bin/bash -c
'apt-get -y update && apt-get install -y git=1:2.20.*'
+ # pre-commit's venv doesn't work with user installs.
# Skip the flake8 hook because the following step will run it.
- name: Run pre-commit hooks
run: >-
docker exec snekbox_test /bin/bash -c
- 'SKIP=flake8 pre-commit run --all-files'
+ 'PIP_USER=0 SKIP=flake8 pre-commit run --all-files'
# This runs `flake8` in the container and asks `flake8` to output
# linting errors in the format of the command for registering workflow
diff --git a/Dockerfile b/Dockerfile
index eefb795..2aee11b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,8 +19,17 @@ RUN git clone \
WORKDIR /nsjail
RUN make
+# ------------------------------------------------------------------------------
FROM python:3.9-slim-buster as base
-ENV PIP_NO_CACHE_DIR=false
+
+# Everything will be a user install to allow snekbox's dependencies to be kept
+# separate from the packages exposed during eval.
+ENV PATH=/root/.local/bin:$PATH \
+ PIP_NO_CACHE_DIR=false \
+ PIP_USER=1 \
+ PIPENV_DONT_USE_PYENV=1 \
+ PIPENV_HIDE_EMOJIS=1 \
+ PIPENV_NOSPIN=1
RUN apt-get -y update \
&& apt-get install -y \
@@ -28,34 +37,26 @@ RUN apt-get -y update \
libnl-route-3-200=3.4.* \
libprotobuf17=3.6.* \
&& rm -rf /var/lib/apt/lists/*
-RUN pip install pipenv==2020.11.4
+RUN pip install pipenv==2020.11.15
COPY --from=builder /nsjail/nsjail /usr/sbin/
RUN chmod +x /usr/sbin/nsjail
+# ------------------------------------------------------------------------------
FROM base as venv
ARG DEV
-ENV PIP_NO_CACHE_DIR=false \
- PIPENV_DONT_USE_PYENV=1 \
- PIPENV_HIDE_EMOJIS=1 \
- PIPENV_NOSPIN=1 \
- PYTHONUSERBASE=/snekbox/user_base
-
COPY Pipfile Pipfile.lock /snekbox/
WORKDIR /snekbox
-RUN if [ -n "${DEV}" ]; \
- then \
- pipenv install --deploy --system --dev; \
- else \
- pipenv install --deploy --system; \
- fi
+# Install to the default user site since PIP_USER is set.
+RUN pipenv install --deploy --system ${DEV:+--dev}
# At the end to avoid re-installing dependencies when only a config changes.
# It's in the venv image because the final image is not used during development.
COPY config/ /snekbox/config
+# ------------------------------------------------------------------------------
FROM venv
ENTRYPOINT ["gunicorn"]
diff --git a/README.md b/README.md
index 453eb4c..f59cf8b 100644
--- a/README.md
+++ b/README.md
@@ -50,19 +50,17 @@ By default, the Python interpreter has no access to any packages besides the
standard library. Even snekbox's own dependencies like Falcon and Gunicorn are
not exposed.
-To expose third-party Python packages during evaluation, install them to the user site:
+To expose third-party Python packages during evaluation, install them to a custom user site:
```sh
-docker exec snekbox /bin/sh -c 'pip install --ignore-installed --user numpy'
+docker exec snekbox /bin/sh -c 'PYTHONUSERBASE=/snekbox/user_base pip install numpy'
```
In the above command, `snekbox` is the name of the running container. The name may be different and can be checked with `docker ps`.
-It's important to use `--user` to install them to the user site, whose base is located at `/snekbox/user_base` within the Docker container. To persist the installed packages, a volume for the directory can be created with Docker. For an example, see [`docker-compose.yml`].
+The packages will be installed to the user site within `/snekbox/user_base`. To persist the installed packages, a volume for the directory can be created with Docker. For an example, see [`docker-compose.yml`].
-`--ignore-installed` is only necessary if installing a package that happens to
-be a dependency of snekbox. Normally, pip would reject the installation because
-it doesn't make a distinction here between the global and user sites.
+If `pip`, `setuptools`, or `wheel` are dependencies or need to be exposed, then use the `--ignore-installed` option with pip. However, note that this will also re-install packages present in the custom user site, effectively making caching it futile. Current limitations of pip don't allow it to ignore packages extant outside the installation destination.
## Development Environment
diff --git a/deployment.yaml b/deployment.yaml
index 988394f..0b294d2 100644
--- a/deployment.yaml
+++ b/deployment.yaml
@@ -30,7 +30,8 @@ spec:
- "/bin/sh"
- "-c"
- >-
- pip install --user --ignore-installed
+ PYTHONUSERBASE=/snekbox/user_base
+ pip install --user
arrow~=0.17
attrs~=20.3
beautifulsoup4~=4.9