Snapd in Docker

Both snapd and docker require significant access to tuning the underlying operating system so that the applications running on top of them can be confined. It’ll definitely take some experimentation and tweaking cycles, probably on both ends, to be able to make that work reliably.

1 Like

The original post shows the mount command used and it is fuse.squashfuse. I had a chat with @evan and he clarified this to me:

If I use mount it fails, if instead I use squashfuse it works

So maybe we can switch to that syntax for mounting the snap?

That’s being done by systemd itself. We’re simply declaring Type=fuse.squashfsfuse in the mount unit.

Stéphane Graber will likely be able to help here since he made snapd work inside LXD.

I’ve running into this issue on the attempt to create ‘classic’ snap in docker.

classic confinement requires the core snap to be installed. Install it by running `snap install core`.

Obviously as snapd is not running in docker container, so there is no way to just install the ‘core’.

Are there any public Dockerfiles that could help me here?

You can set SNAPCRAFT_SETUP_CORE in your docker run. This hasn’t been documented much as of today due to the fact that doing this is only something one would do on a disposable system. I guess a docker run would fit this description.

@evan any thoughts on how to get this into the existing CI documentation for docker?

works fine. Thank you.

@sergiusens Should I look at https://snapcraft.io/ for such information when it will be document, or there are other places?

@sergiusens if we always need to do it for Docker, could we check for /.dockerenv inside snapcraft and set SNAPCRAFT_SETUP_CORE accordingly?

1 Like

Yes, that works, so .dockerenv would always be in CWD?

@sergiusens always in /.dockerenv:

Alternatively (and perhaps a bit more likely to survive future changes), you can check /proc/1/cpuset for “docker”:

 docker run snapcore/snapcraft sh -c "cat /proc/1/cpuset | grep '^/docker' " 
1 Like

you did not install the fuse package and thus are missing /sbin/mount.fuse … so systemd cant actually run mount with -t fuse.$fusefs …

smells like squashfuse simply misses a dependency here …

Thanks @ogra. This is working:

$ cat Dockerfile
FROM ubuntu:16.04
ENV container docker
ENV PATH /snap/bin:$PATH
ADD snap /usr/local/bin/snap
RUN apt-get update
RUN apt-get install -y snapd squashfuse fuse
RUN systemctl enable snapd
STOPSIGNAL SIGRTMIN+3
CMD [ "/sbin/init" ]

And:

$ cat snap
#!/bin/sh -e

while ! kill -0 $(pidof snapd) 2>/dev/null; do
  echo "Waiting for snapd to start."
  sleep 1
done

/usr/bin/snap $@

$ chmod +x snap

Now, build it:

$ docker build -t snapd . 

Run it:

$  docker run --name=snapd -ti -d \                                                                                     
  --tmpfs /run --tmpfs /run/lock --tmpfs /tmp \
  --privileged \ # [1]
  -v /lib/modules:/lib/modules:ro \ # [2]
  snapd

And install some snaps:

$ docker exec -it snapd snap install emoj
$ docker exec -it snapd emoj success
✔  ✅  ☑  📚  👌  🎓  💰

Notes:

  1. Otherwise systemd complains about /sys not being writable when reloading udev rules (ConditionPathIsReadWrite=/sys was not met)

  2. Otherwise strictly confined snaps fail to execute:
    $ docker exec -it snapd emoj
    cannot perform operation: mount --rbind /lib/modules /tmp/snap.rootfs_NCx2ET//lib/modules: No such file or directory

5 Likes

Can I run graphical programs from such environment?

$ sudo docker exec snappy snap install ohmygiraffe
...
$ sudo docker exec snappy ohmygiraffe
AL lib: (WW) ReadALConfig: Ignoring XDG config dir: 
AL lib: (WW) alc_initconfig: Failed to initialize backend "pulse"
ALSA lib conf.c:3750:(snd_config_update_r) Cannot access file /usr/share/alsa/alsa.conf
ALSA lib pcm.c:2266:(snd_pcm_open_noupdate) Unknown PCM default
AL lib: (EE) ALCplaybackAlsa_open: Could not open playback device 'default': No such file or directory
Could not open device.
/snap/ohmygiraffe/3/bin/launch_omg: line 59:   574 Segmentation fault      $SNAP/usr/bin/love $SNAP/oh-my-giraffe.love

you will likely need some exta options to bind mount bits that allow access to pulse on the outside of the container like:

-e PULSE_SERVER=unix:${XDG_RUNTIME_DIR}/pulse/native
-v ${XDG_RUNTIME_DIR}/pulse/native:${XDG_RUNTIME_DIR}/pulse/native

and perhaps also:

--device /dev/snd

(though i’d hope the last one is already there)

@ogra, as I understand, sound doesn’t seem critical here. I’m afraid more important here is the lack of assess to OS graphical system from inside Docker containers. I saw some tricks with X11 socket passthrough to overcome this. Don’t know if something changed since then…

all the errors above refer to audio only, do you also get them when running ohmygiraffe without docker ?

yes, maybe the crash is due sound indeed, but I mean - even if I solve sound problem, I would stuck with graphical one. Isn’t it?
(I didn’t get a chance to try without docker, but I think it would be OK)

How is this progressing, I don’t seem to find anything more recent on this. As someone who develops on Mac but for distro on Linuxes, I’d love to have a way to get snap working. Either under docker, or ideally natively - as it makes the edit/build/test cycle MUCH shorter.

Have you tried Multipass?

I just took a look and Multipass doesnt appear to run on OSX either (I’ve posted an issue in case someone in the multipass group has it running on OSX) but it also is probably non ideal as it would be ‘app on snap on linux on multipass on osx’ which sounds like a recipe for interacting dependency problems. I guess the hope was that someone had completed writing a snap shim for Macs, and at worst a docker image that you could build on.

Hi @Mitra. I found the issue you filed against Multipass. Are you up and running with Multipass on MacOS now?

I use it every day to build apps for distribution on Linux. It has saved me from having to run big VirtualBox VMs for testing. It produces much more consistent results than snapcraft inside Docker did.

Let me know how it’s working for you.