gvisor
gvisor copied to clipboard
Unable to mount unix socket to container
Description
Whenever I try to mount a unix socket to a container by creating a bind volume, runsc fails with a fatal error when creating the container: Error response from daemon: OCI runtime start failed: starting container: starting root container: starting sandbox: failed to setupFS: mounting submounts: mount submount "/var/run/docker.sock": failed to mount "/var/run/docker.sock" (type: bind): input/output error, opts: &{{false false false false} false {trans=fd,rfdno=9,wfdno=9,cache=remote_revalidating {/var/run/docker.sock false false}} true}: unknown
.
Steps to reproduce
Using this docker compose file:
version: "3"
services:
watchtower:
image: containrrr/watchtower
runtime: runsc
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Run docker compose up
and observe the error.
runsc version
runsc version release-20220815.0
spec: 1.0.2-dev
docker version (if using docker)
Client: Docker Engine - Community
Version: 20.10.17
API version: 1.41
Go version: go1.17.11
Git commit: 100c701
Built: Mon Jun 6 23:02:46 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.17
API version: 1.41 (minimum version 1.12)
Go version: go1.17.11
Git commit: a89b842
Built: Mon Jun 6 23:00:51 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.8
GitCommit: 9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
uname
Linux pop-os 5.19.0-76051900-generic #202207312230~1660780566~22.04~9d60db1 SMP PREEMPT_DYNAMIC Thu A x86_64 x86_64 x86_64 GNU/Linux
kubectl (if using Kubernetes)
No response
repo state (if built from source)
No response
runsc debug logs (if available)
I believe runsc blocks unix domain sockets by default. So you need to pass the --fsgofer-host-uds=true
flag to runsc if memory serves. Also, by passing a docker socket, it looks to me like you'd be bypassing the runtime protections runsc offers.
https://github.com/google/gvisor/blob/master/runsc/config/config.go#L74-L76
Thanks for the info, I'll try using that flag. I see via the docs that I can set flags for gvisor globally by modifying /etc/docker/daemon.json
, but is it possible to only pass a flag when starting a specific container?
I'm actually not planning on using watchtower, I just used that as a succinct example. What I plan to do is mount the docker socket in an isolated container that will filter and proxy requests going to it. The application that needs access to the docker socket to function only needs read only access, so I'm planning on using another container to enforce that.
I understand that the proxy container can use the docker socket to gain root access on the host if it's compromised, but I figured wrapping it with gvisor couldn't hurt.
but is it possible to only pass a flag when starting a specific container?
I think you'd need to setup a second runtime in the docker daemon.json, and then use that runtime from kubernetes. So runtime: runsc
-> runtime: runsc-uds
type of idea for containers that need unix domain sockets, and will then invoke runsc with that additional flag.
Correct, you can configure a second runtime with docker/K8s and use it for the container you need socket access. You could also set OCI annotations to set flags to individual containers, but there is no way to set annotations with docker AFAIK. This can be done with K8s or calling runsc
manually.
The annotation format is like this: dev.gvisor.flag.<flag-name>: <value>
Here is an example in K8s to enable debug in a single pod:
metadata:
annotations:
dev.gvisor.flag.debug-log: "/tmp/runsc/sandbox-%ID/"
dev.gvisor.flag.debug: "true"
dev.gvisor.flag.strace: "true"
Note: it requires the runtime to be configured with --allow-flag-override
.