lambci / docker-lambda

Docker images and test runners that replicate the live AWS Lambda environment
MIT License
5.82k stars 430 forks source link

Image provides tmpfs on /dev/shm #26

Open kadrach opened 7 years ago

kadrach commented 7 years ago

The Lambda environment unfortunately does not have a tempfs mounted on /dev/shm, but it is provided by this image.

I can manually fix this by running the container with --privileged, reinstalling util-linux (because /bin/mount is missing) and unmounting /dev/shm.

Python's multiprocessing module uses /dev/shm extensively and does not work properly in AWS Lambda, this is not fully replicated in this docker image.

See issue on AWS forums.

However, this still runs on docker-lambda, but not on AWS Lambda:

from multiprocessing import Pool

def f(x):
    return x*x

p = Pool(5)
print(p.map(f, [1, 2, 3]))
[Errno 38] Function not implemented: OSError
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 9, in lambda_handler
    p = Pool(5)
  File "/usr/lib64/python2.7/multiprocessing/__init__.py", line 232, in Pool
    return Pool(processes, initializer, initargs, maxtasksperchild)
  File "/usr/lib64/python2.7/multiprocessing/pool.py", line 138, in __init__
    self._setup_queues()
  File "/usr/lib64/python2.7/multiprocessing/pool.py", line 234, in _setup_queues
    self._inqueue = SimpleQueue()
  File "/usr/lib64/python2.7/multiprocessing/queues.py", line 354, in __init__
    self._rlock = Lock()
  File "/usr/lib64/python2.7/multiprocessing/synchronize.py", line 147, in __init__
    SemLock.__init__(self, SEMAPHORE, 1, 1)
  File "/usr/lib64/python2.7/multiprocessing/synchronize.py", line 75, in __init__
    sl = self._semlock = _multiprocessing.SemLock(kind, value, maxvalue)
OSError: [Errno 38] Function not implemented
mhart commented 7 years ago

Are you sure this is something that's provided by this image? I haven't checked but I highly doubt it.

If anything it's probably something that Docker itself adds

mhart commented 7 years ago

Confirmed – there's no /dev/shm in the image:

curl -s https://lambci.s3.amazonaws.com/fs/nodejs4.3.tgz | tar -t | grep '^dev/'
dev/
dev/stdout
dev/null
dev/random
dev/full
dev/urandom
dev/zero
dev/stderr
dev/stdin

It appears that Docker adds this when it creates a container (ie, when you docker run) – see the reference here:

https://docs.docker.com/engine/reference/run/#runtime-constraints-on-resources

Specifically the --shm-size arg:

Size of /dev/shm. The format is . number must be greater than 0. Unit is optional and can be b (bytes), k (kilobytes), m (megabytes), or g (gigabytes). If you omit the unit, the system uses bytes. If you omit the size entirely, the system uses 64m.

Given that it must be greater than zero there doesn't seem to be a way to run a container without Docker adding it. You could specify it as one byte – that might have a similar effect? Or you'll have to rely on the complicated unmounting procedure you outlined.

In any case, I don't think there's anything that can be done about the image itself on this front

kadrach commented 7 years ago

I will give that a go, thanks for the quick follow up @mhart !

mhart commented 7 years ago

@kadrach any success on this front?

skunkworker commented 6 years ago

I ran into an issue earlier tonight trying to run chrome headless on lambda. It worked perfectly on the docker container but chrome never launched on lambda until I tracked down that lambda doesn't have /dev/shm with chrome 64+ --disable-dev-shm-usage moves from /dev/shm to /tmp. Could these images also restrict /dev/shm to not exist? like the real lambda environment?

mdavis-xyz commented 3 years ago

Here are some things I tried which do not work:

rm -rf /dev/shm

FROM lambci/lambda:build-python3.8
RUN rm -rf /dev/shm

Permission error because we're not root (but we are)

Overwrite /dev/shm

FROM lambci/lambda:build-python3.8 as src
RUN echo "abc" > /file.dat
FROM lambci/lambda:build-python3.8 as main
COPY --from=src /file.dat /dev/shm

Nope, once again docker build discards the changes to /dev/shm. I think it's not specific to /dev/shm, and actually docker ignores changes to /dev.

--shm-size=0

Running with --shm-size=0 doesn't work. Docker ignores a zero value

Other?

Maybe there's another way to emulate multiprocessing.Pool failing? (e.g. some global python config?) I'm not sure what would do that though. I looked through the relevant cpython code. I'm not sure where exactly the error is thrown. Maybe here?

armeenm commented 2 years ago

--ipc=none works for me.