@@ -26,6 +26,8 @@ type Client struct {
2626 Server * Server
2727 Pty , Tty * os.File
2828 Env Environment
29+ RemoteUser string
30+ ImageName string
2931}
3032
3133// NewClient initializes a new client
@@ -37,13 +39,16 @@ func NewClient(conn *ssh.ServerConn, chans <-chan ssh.NewChannel, reqs <-chan *s
3739 Chans : chans ,
3840 Reqs : reqs ,
3941 Server : server ,
42+ ImageName : conn .User (),
43+ RemoteUser : "nobody" ,
4044 Env : Environment {
4145 "TERM" : os .Getenv ("TERM" ),
4246 "DOCKER_HOST" : os .Getenv ("DOCKER_HOST" ),
4347 "DOCKER_CERT_PATH" : os .Getenv ("DOCKER_CERT_PATH" ),
4448 "DOCKER_TLS_VERIFY" : os .Getenv ("DOCKER_TLS_VERIFY" ),
4549 },
4650 }
51+
4752 clientCounter ++
4853
4954 logrus .Infof ("NewClient (%d): User=%q, ClientVersion=%q" , client .Idx , conn .User (), fmt .Sprintf ("%x" , conn .ClientVersion ()))
@@ -116,12 +121,31 @@ func (c *Client) HandleChannelRequests(channel ssh.Channel, requests <-chan *ssh
116121 }
117122 ok = true
118123
119- args := []string {"run" }
120- args = append (args , c .Server .DockerRunArgs ... )
121- args = append (args , c .Conn .User (), c .Server .DefaultShell )
122- logrus .Debugf ("Executing 'docker %s'" , strings .Join (args , " " ))
123- cmd := exec .Command ("docker" , args ... )
124- cmd .Env = c .Env .List ()
124+ // checking if a container already exists for this user
125+ cmd := exec .Command ("docker" , "ps" , "--filter=label=ssh2docker" , "--filter=label=image:ubuntu" , "--filter=label=user:nobody" , "--quiet" , "--no-trunc" )
126+ buf , err := cmd .CombinedOutput ()
127+ if err != nil {
128+ logrus .Warnf ("docker ps ... failed: %v" , err )
129+ continue
130+ }
131+ existingContainer := strings .TrimSpace (string (buf ))
132+
133+ // Opening Docker process
134+ if existingContainer != "" {
135+ // Attaching to an existing container
136+ args := []string {"exec" , "-it" , existingContainer , c .Server .DefaultShell }
137+ logrus .Debugf ("Executing 'docker %s'" , strings .Join (args , " " ))
138+ cmd = exec .Command ("docker" , args ... )
139+ } else {
140+ // Creating and attaching to a new container
141+ args := []string {"run" }
142+ args = append (args , c .Server .DockerRunArgs ... )
143+ args = append (args , "--label=ssh2docker" , fmt .Sprintf ("--label=user:%s" , c .RemoteUser ), fmt .Sprintf ("--label=image:%s" , c .ImageName ))
144+ args = append (args , c .ImageName , c .Server .DefaultShell )
145+ logrus .Debugf ("Executing 'docker %s'" , strings .Join (args , " " ))
146+ cmd = exec .Command ("docker" , args ... )
147+ cmd .Env = c .Env .List ()
148+ }
125149
126150 defer c .Tty .Close ()
127151 cmd .Stdout = c .Tty
@@ -132,7 +156,7 @@ func (c *Client) HandleChannelRequests(channel ssh.Channel, requests <-chan *ssh
132156 Setsid : true ,
133157 }
134158
135- err : = cmd .Start ()
159+ err = cmd .Start ()
136160 if err != nil {
137161 logrus .Warnf ("cmd.Start failed: %v" , err )
138162 continue
0 commit comments