Score:0

Filesystem mounted with sshfs throws error inside of docker when creating a symlink

us flag

What actual is

I have a server(EX42) and a storage box (BX21) both hosted at Hetzner. On the server runs a peertube instance and I want to save the data on the storage box. I installed sshfs on my Debian 10 root server and mounted the storage box: /etc/fstab:

<user>@<user>.your-storagebox.de:/data  /peertube/data  fuse.sshfs  ssh_command=sshpass\040-f\040/peertube/sftp.pass\040ssh,uid=999,gid=999,allow_other,disable_hardlink,transform_symlinks,reconnect,_netdev  0  0

I mounted the filesystem with the following options regarding symlinks:

-o disable_hardlink
              link(2) will return with errno set to ENOSYS.  Hard links
              don't currently work perfectly on sshfs, and this confuses
              some programs.  If that happens try disabling hard links
              with this option.

-o transform_symlinks
              transform absolute symlinks to relative

Then I start Peertube inside of docker and mount the folder into this container

 peertube:
    volumes:
    - assets:/app/client/dist
    - /peertube/data/peertube:/data
    - /peertube/data/config:/config
    networks:
    - default

The problem

I run a peertube instance with docker and tried to install a plugin with this command:
$: NODE_ENV=production NODE_CONFIG_DIR=/config yarn plugin:install -n peertube-plugin-chapters
The output showed that there is an error with creating a symlink

yarn run v1.22.17
...
2022-03-29 09:35:16.286 error: Cannot install plugin peertube-plugin-chapters, removing it... {
  "err": {
    "err": {
      "stack": "Error: Command failed: yarn add [email protected]\nwarning package.json: No license field\nwarning No license field\nerror An unexpected error occurred: \"EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'\".\n\n    at ChildProcess.exithandler (node:child_process:399:12)\n    at ChildProcess.emit (node:events:526:28)\n    at ChildProcess.emit (node:domain:475:12)\n    at maybeClose (node:internal/child_process:1092:16)\n    at Process.ChildProcess._handle.onexit (node:internal/child_process:302:5)",
      "message": "Command failed: yarn add [email protected]\nwarning package.json: No license field\nwarning No license field\nerror An unexpected error occurred: \"EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'\".\n",
      "killed": false,
      "code": 1,
      "signal": null,
      "cmd": "yarn add [email protected]"
    },
    "stdout": "[1/4] Resolving packages...\n[2/4] Fetching packages...\n[3/4] Linking dependencies...\ninfo If you think this is a bug, please open a bug report with the information provided in \"/data/plugins/yarn-error.log\".\ninfo Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.\n",
    "stderr": "warning package.json: No license field\nwarning No license field\nerror An unexpected error occurred: \"EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'\".\n"
  }
}
...
{
  err: Error: Command failed: yarn add [email protected]
  warning package.json: No license field
  warning No license field
  error An unexpected error occurred: "EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'".
  
      at ChildProcess.exithandler (node:child_process:399:12)
      at ChildProcess.emit (node:events:526:28)
      at ChildProcess.emit (node:domain:475:12)
      at maybeClose (node:internal/child_process:1092:16)
      at Process.ChildProcess._handle.onexit (node:internal/child_process:302:5) {
    killed: false,
    code: 1,
    signal: null,
    cmd: 'yarn add [email protected]'
  },
  stdout: '[1/4] Resolving packages...\n' +
    '[2/4] Fetching packages...\n' +
    '[3/4] Linking dependencies...\n' +
    'info If you think this is a bug, please open a bug report with the information provided in "/data/plugins/yarn-error.log".\n' +
    'info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.\n',
  stderr: 'warning package.json: No license field\n' +
    'warning No license field\n' +
    `error An unexpected error occurred: "EIO: i/o error, symlink '../../../marked/bin/marked' -> '/data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked'".\n`
}
error Command failed with exit code 255.

But when I look inside that folder, I can see the symlink was created and working

$: ls -la /data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/
total 12
drwxr-xr-x 1 peertube peertube  3 Mar 29 09:35 .
drwxr-xr-x 1 peertube peertube  3 Mar 29 09:35 ..
lrwxr-xr-x 1 peertube peertube 26 Mar 29 09:35 marked -> ../../../marked/bin/marked

$: cat /data/plugins/node_modules/peertube-plugin-chapters/node_modules/.bin/marked  
#!/usr/bin/env node

/**
 * Marked CLI
 * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License)
 */

const fs = require('fs'),
  path = require('path'),
  marked = require('../');

/**
 * Man Page
 */

function help() {
  const spawn = require('child_process').spawn;

  const options = {
    cwd: process.cwd(),
    env: process.env,
....

So I tried it myself inside the container with creating a file, symlink it, and modify it

$: echo "Hello" > /data/plugins/hello 
$: cat /data/plugins/hello 
Hello

----

$: ln -s /data/plugins/hello /data/plugins/hello_link
ln: failed to create symbolic link '/data/plugins/hello_link': Input/output error

----

$: cat /data/plugins/hello_link 
Hello

----

$: echo "World" >> /data/plugins/hello_link 

----

$: cat /data/plugins/hello
Hello
World

----

$: ls -la /data/plugins/
total 40
drwxr-xr-x 1 peertube peertube   10 Mar 29 09:38 .
drwxr-xr-x 1 peertube peertube   16 Mar 29 06:32 ..
drwxr-xr-x 1 peertube peertube    2 Mar 28 16:48 .DAV
drwxr-xr-x 1 peertube peertube    3 Mar 28 16:48 data
-rw-r--r-- 1 peertube peertube   12 Mar 29 09:38 hello
lrwxr-xr-x 1 peertube peertube    5 Mar 29 09:38 hello_link -> hello
drwxr-xr-x 1 peertube peertube    6 Mar 29 06:35 node_modules
-rw-r--r-- 1 peertube peertube   76 Mar 28 16:48 package.json
-rw-r--r-- 1 peertube peertube 1248 Mar 29 09:35 yarn-error.log
-rw-r--r-- 1 peertube peertube  413 Mar 28 16:48 yarn.lock

The ln -s command throws an error, but otherwise everything looks fine and works as expected.

What I tried

I also tried to mount the storage with this option

-o follow_symlinks
    follow symlinks on the server 

but all that does was breaking files, and I couldn't delete them anymore, when the link target file was not existing anymore. So, I removed this option again.

I asked the customer support if symlink is supported, and the answer was "yes it is supported".

When I create symlinks on the server directly, it works without problems.

I tried to mount the folder inside of the container at the same folder as on the server
/etc/fstab:

<user>@<user>.your-storagebox.de:/data  /var/peertube/data  fuse.sshfs  ssh_command=sshpass\040-f\040/peertube/sftp.pass\040ssh,uid=999,gid=999,allow_other,disable_hardlink,transform_symlinks,reconnect,_netdev  0  0
 peertube:
    volumes:
    - assets:/app/client/dist
    - /var/peertube/data:/var/peertube/data
    - /peertube/data/config:/config
    networks:
    - default

but this didn't help.

The question

It appears to me that, as soon as I mount the sshfs inside a docker container, it can't create any symlinks without this error message.

What do I need to do to get it to work inside of docker?

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.