2

I'm using node-ssh module on nodejs. When I start the connection to ssh it's giving error. Also I'm using WSL Ubuntu 18. I have docker-compose file. I marked PasswordAuthentication as 'yes' on /etc/ssh/sshd_config. I can connect ssh from wsl ubuntu. But when I was trying to connect from my dockerized nodejs project. It's giving error ECONNREFUSED 127.0.0.1:22

On nodejs I'm making a request for user authentication, running some commands, etc.

const Client = require('node-ssh').NodeSSH;
var client   = new Client();   

client.connect({
     host              : 'localhost',
     port              : 22,
     username          : req.body.username,
     password          : req.body.password,
     keepaliveInterval : 30 * 1000, // 30 minutes for idle as milliseconds
     keepaliveCountMax : 1,
}).then(()=>{

     // LOGIN SUCCESS

}).catch((e)=>{

     console.log(e); // ECONFUSED ERROR
     // LOGIN FAILED

});

docker-compose.yml

version: '3.8'

services:
  api:
    build:
      dockerfile: Dockerfile
      context: "./server"
    ports:
      - "3030:3030"
    depends_on:
      - mysql_db
    volumes:
      - /app/node_modules
      - ./server:/app

 ...

And my api's Dockerfile

Dockerfile

FROM node:alpine
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
COPY ./ ./
RUN npm i
RUN apk update \
&& apk add openssh-server 
COPY sshd_config /etc/ssh/
EXPOSE 22
CMD ["npm", "run", "start"]

[UPDATE__] [Dockerfile]

FROM node:alpine
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
COPY ./ ./
RUN npm i \
&& apk add --update openssh \
&& rm  -rf /tmp/* /var/cache/apk/*
COPY sshd_config /etc/ssh/
# add entrypoint script
ADD ./docker-entrypoint.sh /usr/local/bin
# make sure we get fresh keys
RUN rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key
EXPOSE 22
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["/usr/sbin/sshd","-D"]

[UPDATE__2] [Dockerfile]

FROM node:alpine
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
COPY ./ ./
RUN npm i
RUN apk update && \
apk add openssh-client \ 
&& rm -rf /tmp/* /var/cache/apk/*

EXPOSE 22
CMD ["npm", "run", "start"]

[SOLUTION]
I have changed Dockerfile and my nodejs code. I have connected WSL's SSH from docker container after applying as Stefan Golubović suggested host.docker.internal. And used node:latest instead of node:alpine docker image. Thanks to @StefanGolubović and @Etienne Dijon

[FIXED]

const Client = require('node-ssh').NodeSSH;
var client   = new Client();   

client.connect({
     host              : 'host.docker.internal', // It's worked on WSL2
     port              : 22,
     username          : req.body.username,
     password          : req.body.password,
     keepaliveInterval : 30 * 1000, // 30 minutes for idle as milliseconds
     keepaliveCountMax : 1,
}).then(()=>{

     // LOGIN SUCCESS

}).catch((e)=>{

     console.log(e); // ECONFUSED ERROR
     // LOGIN FAILED

});

Dockerfile [FIXED]

FROM node:latest
WORKDIR /app
COPY package.json ./
COPY package-lock.json ./
COPY ./ ./
RUN npm i
RUN apt-get update 
EXPOSE 22
CMD ["npm", "run", "start"]
rewrewty1
  • 41
  • 6
  • I would try `0.0.0.0` instead of `localhost`. It doesn't make sense to try to connect to localhost from docker container, unless your service is also running in the same container. Also, you could try [`host.docker.internal`](https://docs.docker.com/desktop/windows/networking/#use-cases-and-workarounds), or `gateway.docker.internal` instead of `localhost`. – Stefan Golubović Oct 04 '21 at 14:20
  • I think your keepaliveInterval may need to also multiply by 60 to be 30 minutes. For the SSH error - do you have OpenSSH Server enabled on Windows 10? If you run `netstat -ab` from cmd, does it show that port 22 is listening? – zacran Oct 04 '21 at 14:23
  • @StefanGolubović I tried `0.0.0.0` but same error. – rewrewty1 Oct 04 '21 at 15:38
  • @zacran Yes it does show port 22 is listening. But above the line say "Can not obtain ownership information" [wslhost.exe] – rewrewty1 Oct 04 '21 at 15:41
  • Now I can connect WSL's SSH from docker container with `host.docker.internal`. I changed `host` variable to host.docker.internal. Thanks @StefanGolubović you saved my time :) – rewrewty1 Oct 11 '21 at 12:34

1 Answers1

2

Short answer

Test step by step your dockerfile

Something you can do to make sure everything works fine is to run it manually

docker run -it --rm --name testalpine -v $PWD:/app/ node:alpine /bin/sh

Then :

cd /app/
npm i
apk update && apk add openssh-server
# show listening services, openssh is not displayed
netstat -tlpn

As you can see, openssh is not started automatically

Alpine has a wiki about it which needs rc-update :

https://wiki.alpinelinux.org/wiki/Setting_up_a_ssh-server

rc-update is not available in alpine image.

Running sshd server in an alpine container

This image is all about running a ssh server on alpine :

https://github.com/danielguerra69/alpine-sshd

As you can see in Dockerfile, more steps are involved :

Check repository for updated dockerfile

FROM alpine:edge
MAINTAINER Daniel Guerra <daniel.guerra69@gmail.com>

# add openssh and clean
RUN apk add --update openssh \
&& rm  -rf /tmp/* /var/cache/apk/*
# add entrypoint script
ADD docker-entrypoint.sh /usr/local/bin
# make sure we get fresh keys
RUN rm -rf /etc/ssh/ssh_host_rsa_key /etc/ssh/ssh_host_dsa_key

EXPOSE 22
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["/usr/sbin/sshd","-D"]

EDIT: If you need to run commands within your container

You can use docker exec once your container is started:

docker exec -it <container name/id> /bin/sh

documentation here :

https://docs.docker.com/engine/reference/commandline/exec/

  • Updated dockerfile
    FROM node:alpine
    
    WORKDIR /app
    
    COPY ./ ./
    
    RUN npm i
    
    ENTRYPOINT ["npm", "run", "start"]
    
Etienne Dijon
  • 1,093
  • 5
  • 10
  • Thanks for your reply. I tried your solutions but it's not working. Daniel Guerra's image is not containing npm so I can't use npm command. Other way when I use `node:alpine` and `docker-entrypoint.sh` you have give, I'm getting error : `standard_init_linux.go:228: exec user process caused: no such file or directory`. I updated question for you. You can look my Dockerfile and docker-compose file with `[Update__]` tag. – rewrewty1 Oct 06 '21 at 09:13
  • Also I'm using command `docker-compose up --build` for container up – rewrewty1 Oct 06 '21 at 09:19
  • Hello @rewrewty1, is ssh needed to initialize your container ? in that case, could you add commands your need to run, the idea could be to change the entrypoint without using ssh at all. – Etienne Dijon Oct 06 '21 at 09:19
  • Yes it's need to be started when my container started. On my nodejs project I will using so many times ssh not one time – rewrewty1 Oct 06 '21 at 09:24
  • Please see my edit, docker exec should do the trick. – Etienne Dijon Oct 06 '21 at 09:39
  • I understood what you want to tell me. Now ssh installed on my image. But when I trying to connect wsl's ssh from my container I can't log in to. It's giving error like this `Permisison Denied. Please try again` although my password was true – rewrewty1 Oct 07 '21 at 11:41
  • Maybe you're looking for something like this :https://stackoverflow.com/a/52120176/16762357 – Etienne Dijon Oct 07 '21 at 18:32
  • I checked the link you posted. For now problem is we can't access the wsl via `0.0.0.0`. But when I check the ip address on wsl via ifconfig it says your ip is 172.30.X.X. And when I connect with this address there is no problem. Currently the problem is how can I get the wsl ip without manual. And I updated my dockerfile like on the `UPDATE__2` tag. Maybe someone benefit – rewrewty1 Oct 08 '21 at 08:59
  • My problem is resolved. Yes you was right when you said sshd server is not started automatically by default on alpine. So I used node:latest. This was my first problem. And second problem is resolved by @Stefan Golubović 's prefer – rewrewty1 Oct 11 '21 at 12:38
  • Many thanks for your feedback, could you add an answer with your working solution, it could help others. thanks again. – Etienne Dijon Oct 11 '21 at 13:00