I am trying to mount a directory located on a host from a docker container using sshfs. The problem I am having is that once the golang app finishes executing the mountpoint disappears whereas it suppose to persist (the same steps performed manually are producing persistent results.
The ssh client code:
package main
import (
//"bytes"
"code.google.com/p/go.crypto/ssh"
//"fmt"
"io"
"log"
"os"
)
var (
server = "172.17.42.1:49155"
username = "root"
password = clientPassword("orobix2013")
)
type clientPassword string
func (p clientPassword) Password(user string) (string, error) {
return string(p), nil
}
type TerminalModes map[uint8]uint32
const (
VINTR = 1
VQUIT = 2
VERASE = 3
VKILL = 4
VEOF = 5
VEOL = 6
VEOL2 = 7
VSTART = 8
VSTOP = 9
VSUSP = 10
VDSUSP = 11
VREPRINT = 12
VWERASE = 13
VLNEXT = 14
VFLUSH = 15
VSWTCH = 16
VSTATUS = 17
VDISCARD = 18
IGNPAR = 30
PARMRK = 31
INPCK = 32
ISTRIP = 33
INLCR = 34
IGNCR = 35
ICRNL = 36
IUCLC = 37
IXON = 38
IXANY = 39
IXOFF = 40
IMAXBEL = 41
ISIG = 50
ICANON = 51
XCASE = 52
ECHO = 53
ECHOE = 54
ECHOK = 55
ECHONL = 56
NOFLSH = 57
TOSTOP = 58
IEXTEN = 59
ECHOCTL = 60
ECHOKE = 61
PENDIN = 62
OPOST = 70
OLCUC = 71
ONLCR = 72
OCRNL = 73
ONOCR = 74
ONLRET = 75
CS7 = 90
CS8 = 91
PARENB = 92
PARODD = 93
TTY_OP_ISPEED = 128
TTY_OP_OSPEED = 129
)
func main() {
// An SSH client is represented with a slete). Currently only
// the "password" authentication method is supported.
//
// To authenticate with the remote server you must pass at least one
// implementation of ClientAuth via the Auth field in ClientConfig.
config := &ssh.ClientConfig{
User: username,
Auth: []ssh.ClientAuth{
// ClientAuthPassword wraps a ClientPassword implementation
// in a type that implements ClientAuth.
ssh.ClientAuthPassword(password),
},
}
client, err := ssh.Dial("tcp", "172.17.42.1:49155", config)
if err != nil {
panic("Failed to dial: " + err.Error())
}
// Each ClientConn can support multiple interactive sessions,
// represented by a Session.
defer client.Close()
// Create a session
session, err := client.NewSession()
if err != nil {
log.Fatalf("unable to create session: %s", err)
}
defer session.Close()
// Set up terminal modes
modes := ssh.TerminalModes{
ECHO: 0, // disable echoing
TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
// Request pseudo terminal
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
log.Fatalf("request for pseudo terminal failed: %s", err)
}
//var b bytes.Buffer
//session.Stdout = &bi
stdin, _ := session.StdinPipe()
stdout, _ := session.StdoutPipe()
go io.Copy(os.Stdout, stdout)
go io.Copy(stdin, os.Stdin)
//go io.Copy(os.Stderr, stderr)
if err := session.Run("/bin/bash -c \"sshfs piotr@172.17.42.1:/home/piotr/helloworld/ /mnt -o idmap=user -o reconnect;touch /mnt/ofoo\""); err != nil {
panic("Failed to run: " + err.Error())
}
The container is running in the background (-d) and I ssh into it to confrim that the mountpoint(/mnt/) is still there and this is what I am getting:
root@654b8fa08b9e:~# mount
none on / type aufs (rw,relatime,si=77b99811b9d139a9)
/dev/disk/by-uuid/7e1d6bab-b3f2-4ac3-8bff-0779f5bf40f2 on /etc/hostname type ext4 (ro,relatime,errors=remount-ro,data=ordered)
/dev/disk/by-uuid/7e1d6bab-b3f2-4ac3-8bff-0779f5bf40f2 on /etc/hosts type ext4 (ro,relatime,errors=remount-ro,data=ordered)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
/dev/disk/by-uuid/7e1d6bab-b3f2-4ac3-8bff-0779f5bf40f2 on /.dockerinit type ext4 (ro,relatime,errors=remount-ro,data=ordered)
/dev/disk/by-uuid/7e1d6bab-b3f2-4ac3-8bff-0779f5bf40f2 on /etc/resolv.conf type ext4 (ro,relatime,errors=remount-ro,data=ordered)
devpts on /dev/tty1 type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=666)
devpts on /dev/ptmx type devpts (rw,relatime,mode=600,ptmxmode=666)
piotr@172.17.42.1:/home/piotr/helloworld/ on /mnt type fuse.sshfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,max_read=65536)
root@654b8fa08b9e:~# cd /mnt/
root@654b8fa08b9e:/mnt# ls
ls: reading directory .: Input/output error
root@654b8fa08b9e:/mnt#
THe "mount" command shows that the mountpoint is there however when I am trying to access it I am getting: ls: reading directory .: Input/output error
Can someone tell me how I can fix that please? I spend quite a lot of time on this without success, any input is very welcome!
How to test it:
I uploaded my testing docker container to the public repository so you can run and test it now yourself:
First you need to start the container in the background with sshd running:
sudo docker run -i -t -privileged -dns=172.25.0.10 -p 22 -d orobix/sshfs_startup_key2 /bin/bash -c "/usr/sbin/sshd -D"
privileged is needed for the sshfs fuse system to work, I use dns option to specify my dns server because I am inside a local network(you might not need to) The image(orobix/ssfs_startuo_key2) should be pulled automatically from the public repository.
Once the container is running you should be able to run the go code(of course ip addresses must be changed).
You can ssh into container manually with e.g.:
ssh root@172.17.42.1 -p 49153
Again, ip and ports will be different.