jacobsa/fuse

How to run in Docker container?

Closed this issue · 2 comments

Hello,

TL;DR: I want to get jacobsa/fuse running in a Linux-based Docker container.

I've been trying to run my basic FS implementation in a docker container, but jacobsa/fuse does not seem to be working in the container. I have outlined the steps I have taken to set the environment up. Let me know if I am missing any steps or dependencies.

I am using privileged mode in a ubuntu:latest docker container.

docker run --privileged --name go-fuse-container -it --device /dev/fuse --cap-add SYS_ADMIN ubuntu bash

Inside my container, I start with basic steps.

apt update
apt install sudo

Next, I install Go v1.22.3

sudo apt install wget
wget https://go.dev/dl/go1.22.3.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.22.3.linux-amd64.tar.gz
rm go1.22.3.linux-amd64.tar.gz


export PATH="/usr/local/go/bin:${PATH}"
export GOPATH="/go"
export PATH="${GOPATH}/bin:${PATH}"

I move on to installing FUSE.

sudo apt install kmod
sudo apt install fuse

Note that installing fuse also installs libfuse2.

At this point, I ran modprobe fuse and received this error (suggesting that the FUSE installation may not have succeeded):

modprobe: FATAL: Module fuse not found in directory /lib/modules/6.6.26-linuxkit

To test out my installation, I ran the mount_hello program in samples.

go run mount.go --mount_point ./dir

This was the output:

2024/07/12 19:22:02 Mount: mount: invalid argument
exit status 1

I have tested the program on other machines and can confidently say it works. Thus, my conclusion is that FUSE may not have been properly setup on the container to enable usage of jacobsa/fuse.

However, I tested using s3fs on the same system and it worked just fine. I also tested fusepy, which also worked. Not sure why jacobsa/fuse is not working. Would truly appreciate any help. Feel free to ask for more information on OS version, fuse versions, etc.

Thanks in advance!

I compared the strace -fvy -s 2048 output of running a libfuse example:

newfstatat(AT_FDCWD</root/libfuse/build/example>, "/root/libfuse/build/example/dir", {st_dev=makedev(0, 0x48), st_ino=60140651, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=1721550190 /* 2024-07-21T08:23:10.114755300+0000 */, st_atime_nsec=114755300, st_mtime=1721550171 /* 2024-07-21T08:22:51.580984541+0000 */, st_mtime_nsec=580984541, st_ctime=1721550171 /* 2024-07-21T08:22:51.580984541+0000 */, st_ctime_nsec=580984541}, 0) = 0
openat(AT_FDCWD</root/libfuse/build/example>, "/dev/fuse", O_RDWR|O_CLOEXEC) = 3</dev/fuse>
getgid()                                = 0
getuid()                                = 0
mount("hello_ll", "/root/libfuse/build/example/dir", "fuse.hello_ll", MS_NOSUID|MS_NODEV, "fd=3,rootmode=40000,user_id=0,group_id=0") = 0
geteuid()                               = 0
readlink("/root", 0x7fff940b5f30, 1023) = -1 EINVAL (Invalid argument)
readlink("/root/libfuse", 0x7fff940b5f30, 1023) = -1 EINVAL (Invalid argument)
readlink("/root/libfuse/build", 0x7fff940b5f30, 1023) = -1 EINVAL (Invalid argument)
readlink("/root/libfuse/build/example", 0x7fff940b5f30, 1023) = -1 EINVAL (Invalid argument)
newfstatat(AT_FDCWD</root/libfuse/build/example>, "/etc/mtab", {st_dev=makedev(0, 0x48), st_ino=51463348, st_mode=S_IFLNK|0777, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=0, st_size=12, st_atime=1721549992 /* 2024-07-21T08:19:52.100006086+0000 */, st_atime_nsec=100006086, st_mtime=1721549992 /* 2024-07-21T08:19:52.100006086+0000 */, st_mtime_nsec=100006086, st_ctime=1721549992 /* 2024-07-21T08:19:52.100006086+0000 */, st_ctime_nsec=100006086}, AT_SYMLINK_NOFOLLOW) = 0
getuid()                                = 0
access("/etc/mtab", W_OK)               = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLDstrace: Process 6204 attached
, child_tidptr=0x727ce8a8ba10) = 6204
[pid  6203] wait4(6204,  <unfinished ...>
[pid  6204] set_robust_list(0x727ce8a8ba20, 24) = 0
[pid  6204] rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
[pid  6204] geteuid()                   = 0
[pid  6204] setuid(0)                   = 0
[pid  6204] execve("/bin/mount", ["/bin/mount", "--no-canonicalize", "-i", "-f", "-t", "fuse.hello_ll", "-o", "rw,nosuid,nodev", "hello_ll", "/root/libfuse/build/example/dir"], []) = 0

with the output of stracing the jacobsa/fuse/samples/mount_hello example:

[pid  6671] newfstatat(AT_FDCWD</root/fuse/samples/mount_hello>, "/root/fuse/samples/mount_hello/dir",  <unfinished ...>
[pid  6677] futex(0x6543d8, FUTEX_WAIT_PRIVATE, 0, NULL <unfinished ...>
[pid  6671] <... newfstatat resumed>{st_dev=makedev(0, 0x48), st_ino=55069252, st_mode=S_IFDIR|0755, st_nlink=2, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=8, st_size=4096, st_atime=1721550050 /* 2024-07-21T08:20:50.594761170+0000 */, st_atime_nsec=594761170, st_mtime=1721550050 /* 2024-07-21T08:20:50.594761170+0000 */, st_mtime_nsec=594761170, st_ctime=1721550050 /* 2024-07-21T08:20:50.594761170+0000 */, st_ctime_nsec=594761170}, 0) = 0
[pid  6672] <... nanosleep resumed>NULL) = 0
[pid  6672] nanosleep({tv_sec=0, tv_nsec=20000},  <unfinished ...>
[pid  6671] openat(AT_FDCWD</root/fuse/samples/mount_hello>, "/dev/fuse", O_RDWR <unfinished ...>
[pid  6672] <... nanosleep resumed>NULL) = 0
[pid  6671] <... openat resumed>)       = 3</dev/fuse>
[pid  6672] nanosleep({tv_sec=0, tv_nsec=20000},  <unfinished ...>
[pid  6671] fcntl(3</dev/fuse>, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE)
[pid  6671] getuid( <unfinished ...>
[pid  6672] <... nanosleep resumed>NULL) = 0
[pid  6671] <... getuid resumed>)       = 0
[pid  6671] getgid( <unfinished ...>
[pid  6672] nanosleep({tv_sec=0, tv_nsec=20000},  <unfinished ...>
[pid  6671] <... getgid resumed>)       = 0
[pid  6672] <... nanosleep resumed>NULL) = 0
[pid  6671] mount("", "/root/fuse/samples/mount_hello/dir", "fuse", MS_NOSUID|MS_NODEV, "fd=3,rootmode=40000,user_id=0,group_id=0,default_permissions" <unfinished ...>
[pid  6672] nanosleep({tv_sec=0, tv_nsec=20000},  <unfinished ...>
[pid  6671] <... mount resumed>)        = -1 EINVAL (Invalid argument)
[pid  6672] <... nanosleep resumed>NULL) = 0
[pid  6672] nanosleep({tv_sec=0, tv_nsec=20000},  <unfinished ...>
[pid  6671] openat(AT_FDCWD</root/fuse/samples/mount_hello>, "/etc/localtime", O_RDONLY <unfinished ...>
[pid  6672] <... nanosleep resumed>NULL) = 0
[pid  6671] <... openat resumed>)       = -1 ENOENT (No such file or directory)

Note how the first mount() parameter is empty.

On the host (not in Docker), I can see these error messages in dmesg:

[1110393.704391] fuse: Bad value for 'source'

I’ll submit a fix.

Awesome! Thanks so much, @stapelberg