Issue
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"]
Solution
Short answer
sshd
server is not started automatically by default onalpine
.You may use an other node image to run your application like
node:latest
https://hub.docker.com/_/nodebased on debian, equivalent version alternative to node:alpine
Try to avoid ssh in a docker container, you may use a script as entrypoint to configure your container at runtime
Documentation : https://docs.docker.com/engine/reference/builder/#entrypoint
Best practices with example of script : https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#entrypoint
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 <[email protected]>
# 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"]
Answered By - Etienne Dijon