Many of the Kubernetes cluster and Docker on production, have a policy to run on read-only system for all the directory except certain explicit folder that customizable by user. In read-only file system, not all of the application can run smooth by default, but trivial to fix as well.
For this tutorial lets take pip
as the example, and run everything from docker for easiness
Run the normal docker image
$ docker run -it python:3.11.9-slim-bookworm touch temp.txt
the command touch temp.txt
will executed successfully, hence no error
lets try with read-only file system, we’ll get the error
$ docker run -it --read-only python:3.11.9-slim-bookworm touch temp.txt touch: cannot touch 'temp.txt': Read-only file system
Run pip Inside Docker
Let’s install boto3
using pip
root@9155d3e213cc:/# pip install boto3 Defaulting to user installation because normal site-packages is not writeable ERROR: Exception: Traceback (most recent call last): File "/usr/local/lib/python3.11/site-packages/pip/_internal/cli/base_command.py", line 180, in exc_logging_wrapper status = run_func(*args) ^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/pip/_internal/cli/req_command.py", line 245, in wrapper return func(self, options, args) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/pip/_internal/commands/install.py", line 333, in run build_tracker = self.enter_context(get_build_tracker()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/pip/_internal/cli/command_context.py", line 27, in enter_context return self._main_context.enter_context(context_provider) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/contextlib.py", line 517, in enter_context result = _enter(cm) ^^^^^^^^^^ File "/usr/local/lib/python3.11/contextlib.py", line 137, in __enter__ return next(self.gen) ^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/pip/_internal/operations/build/build_tracker.py", line 46, in get_build_tracker root = ctx.enter_context(TempDirectory(kind="build-tracker")).path ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/pip/_internal/utils/temp_dir.py", line 137, in __init__ path = self._create(kind) ^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/pip/_internal/utils/temp_dir.py", line 177, in _create path = os.path.realpath(tempfile.mkdtemp(prefix=f"pip-{kind}-")) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/tempfile.py", line 374, in mkdtemp prefix, suffix, dir, output_type = _sanitize_params(prefix, suffix, dir) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/tempfile.py", line 127, in _sanitize_params dir = gettempdir() ^^^^^^^^^^^^ File "/usr/local/lib/python3.11/tempfile.py", line 316, in gettempdir return _os.fsdecode(_gettempdir()) ^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/tempfile.py", line 309, in _gettempdir tempdir = _get_default_tempdir() ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/tempfile.py", line 224, in _get_default_tempdir raise FileNotFoundError(_errno.ENOENT, FileNotFoundError: [Errno 2] No usable temporary directory found in ['/tmp', '/var/tmp', '/usr/tmp', '/'] WARNING: There was an error checking the latest version of pip.
this happens, because the folder ‘/tmp’, ‘/var/tmp’, ‘/usr/tmp’, ‘/’ is read-only, so the pip cannot store the data there. This issue fixable by define the TMPDIR variable environment to directory that had access read-write. The solution will provided on the bottom.
tmpfs for the rescue
Modify the command by add the --tmpfs DIR
$ docker run -it --read-only --tmpfs /app python:3.11.9-slim-bookworm bash root@11d6469dd010:/# touch /app/temp.txt; ls -lah /app/temp.txt -rw-r--r-- 1 root root 0 Apr 5 14:42 /app/temp.txt root@11d6469dd010:/#
from testing above we can write file to directory /app
, set the TMPDIR to /app and try install boto3 again
$ docker run -it --read-only --tmpfs /app python:3.11.9-slim-bookworm bash root@11d6469dd010:/# export TMPDIR=/app root@11d6469dd010:/# pip install boto3 Defaulting to user installation because normal site-packages is not writeable <snip> Installing collected packages: urllib3, six, jmespath, python-dateutil, botocore, s3transfer, boto3 ERROR: Could not install packages due to an OSError: [Errno 30] Read-only file system: '/root/.local' WARNING: There was an error checking the latest version of pip.
pip DATADIR
The solution here is to combine TMPDIR and --datadir
export TMPDIR=/app # set the PYTHONPATH to /app export PYTHONPATH=/app pip install --target /app boto3
For production environment create a non-privileges user to run the app inside the docker