openssh远程连接docker

使用openssh我们可以将Docker启动的容器当做一个小型的服务器来使用,这样我们登陆容器的时候就可以用ssh root@xx.xx.xx来登陆使用了

注意:使用openssh登录docker有两种方法,一种是秘钥登录,另一种是密码登录,不论是秘钥登录还是密码登录都需要安装openssh。这里对于秘钥登录我们给出dockerfile,对于密码登录我们手动安装,当然也可以根据需求是选择创建镜像时安装还是建好docker后在安装

1. 秘钥登录

1.1 Dockerfile构建

首先免密登陆容器需要秘钥,这里我们将本机的ssh文件夹放在与Dockerfile相同的文件夹下

ssh文件夹一般在/home/root/.ssh

然后编写我们的Dockerfile,下面的dockerfile意思是说将本地的ssh文件夹传到容器中,然后安装openssh-server,随后修改密钥登陆,禁止密码登录

1
2
3
4
5
6
7
8
# openssh server
COPY ~/.ssh/ /root/.ssh/
RUN apt-get install -y openssh-server && \
cat ~/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys && \
chmod 600 /root/.ssh/authorized_keys /root/.ssh/id_rsa.pub /root/.ssh/id_rsa && \
sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config && \
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && \
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/g' /etc/ssh/sshd_config

上述代码是核心ssh代码,其余内容按照自己需求定制即可,然后我们构建镜像,并通过docker run -it -p 2134:22 image:tag /bin/bash创建容器,然后运行ssh -p port root@0.0.0.0(有时候0.0.0.0要用本机的ip),远程连接时会出现如下错误,解决这个问题只需要在容器中运行service ssh restart即可。

1
ssh: connect to host 192.168.9.148 port 2134: Connection refused

但是这样每次关闭容器后需要再次运行上述代码,很麻烦,因此我们写入一个脚本来每次登陆容器时自动运行上述命令,在上述ssh的下面加入以下代码即可。一共分为三部分,第一部分写一个shell文件来自动启动ssh,第二部分通过.bashrc文件检测shell文件的存在,如果存在则运行,最后更新.bashrc即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# auto start openssh
RUN touch /startup_run.sh && \
chmod 600 /startup_run.sh && \
echo '#!/bin/bash' >> /startup_run.sh && \
echo 'LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")' >> /startup_run.sh && \
echo 'echo "[$LOGTIME] startup run..." >> /root/startup_run.log' >> /startup_run.sh && \
echo 'service ssh start >> /root/startup_run.log' >> /startup_run.sh && \
chmod +x /startup_run.sh

# setup .bashrc to auto run startup_run.sh
RUN echo '# startup run' | tee -a /root/.bashrc && \
echo 'if [ -f /startup_run.sh ]; then' | tee -a /root/.bashrc && \
echo ' /startup_run.sh' | tee -a /root/.bashrc && \
echo 'fi' | tee -a /root/.bashrc
RUN /bin/bash -c "source ~/.bashrc"

1.2 ssh连接容器

这部分在上述Dockerfile中已经写过了,这里在做一下总结。

首先根据Dockerfile创建一个镜像

1
docker build -t <image:tag> .

根据我们的镜像创建一个容器

1
docker run -it -p 3712:22 image:tag /bin/bash

此时容器已经打开了,然后我们在另一个终端或者在vscode中通过ssh远程连接即可,这里的ip有时候为本机ip,有时候为0.0.0.0,可以通过docker ps查看,然后用下面命令连接

1
ssh root@ip -p 3712

1.3 命令解释

  1. COPY .ssh/ /root/.ssh/表示将本地的.ssh文件复制到容器中的/root/.ssh/文件夹下(其实这里相当于把副武器的ssh整个内容加入到了docker容器中)
  2. 其中的apt-get install -y openssh-server表示安装openssh-server服务,这样就可以允许秘钥登陆了
  3. cat ~/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys将本地用户的公钥写入到容器中的authorized_keys文件中,这样本地就可以ssh自动登录到容器中了
  4. PubkeyAuthentication是否允许公钥登陆
  5. PasswordAuthentication是否允许密码登录
  6. PermitRootLogin参数为noyesprohibit-passwordno表示不允许root用户登录,yes表示允许root用户登录,prohibit-password表示不允许root用户使用密码登录

1.4 整个Dockerfile文件

要先把.sshminiconda.sh文件和Dockerfile文件放在同一目录下才能build

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
FROM nvidia/cuda:11.7.1-devel-ubuntu20.04
LABEL maintainer wangyh "1061771439@qq.com"

# setup proxy
# ENV http_proxy http://192.168.161.204:7890
# ENV https_proxy http://192.168.161.204:7890

ENV PATH /opt/conda/bin:$PATH
COPY miniconda.sh /miniconda.sh

# install some tools
RUN chmod -R 777 /opt && \
APT_INSTALL="apt-get install -y --no-install-recommends" && \
CONDA_INSTALL="conda install -y" && \
rm -rf /var/lib/apt/lists/* \
/etc/apt/sources.list.d/cuda.list \
/etc/apt/sources.list.d/nvidia-ml.list && \
apt-get update && \
apt-get -y upgrade && \
$APT_INSTALL wget vim zip git libgl1-mesa-glx libglib2.0-0 && \
$APT_INSTALL openssh-server

# install miniconda
RUN rm -rf /opt/conda && \
/bin/bash /miniconda.sh -b -p /opt/conda && \
rm /miniconda.sh && \
pip install --upgrade pip && \
conda create -n torch -y python=3.10

RUN echo "conda activate torch" >> ~/.bashrc
# RUN python -c "import flask"
SHELL ["/bin/bash", "--login", "-c"]

# setup openssh
RUN mkdir -p /var/run/sshd
RUN mkdir -p /root/.ssh

COPY .ssh/ /root/.ssh/
RUN cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
RUN chmod 600 /root/.ssh/authorized_keys /root/.ssh/id_rsa.pub /root/.ssh/id_rsa && \
sed -i 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/g' /etc/ssh/sshd_config && \
sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && \
sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin prohibit-password/g' /etc/ssh/sshd_config

# auto start openssh
RUN touch /startup_run.sh && \
chmod 600 /startup_run.sh && \
echo '#!/bin/bash' >> /startup_run.sh && \
echo 'LOGTIME=$(date "+%Y-%m-%d %H:%M:%S")' >> /startup_run.sh && \
echo 'echo "[$LOGTIME] startup run..." >> /root/startup_run.log' >> /startup_run.sh && \
echo 'service ssh start >> /root/startup_run.log' >> /startup_run.sh && \
chmod +x /startup_run.sh

# setup .bashrc to auto run startup_run.sh
RUN echo '# startup run' | tee -a /root/.bashrc && \
echo 'if [ -f /startup_run.sh ]; then' | tee -a /root/.bashrc && \
echo ' /startup_run.sh' | tee -a /root/.bashrc && \
echo 'fi' | tee -a /root/.bashrc
RUN /bin/bash -c "source ~/.bashrc"

# install python packages
RUN pip install medpy cython opencv-python cmake blobfile scipy scikit-image

RUN conda clean -y --all && \
ldconfig && \
apt-get clean && \
apt-get autoremove && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ~/*

2. 密码登录

2.1 安装openssh

这里我们创建一个普通容器不包含Openssh,并使用如下命令进入容器

1
docker run -it xx/xx:xx /bin/bash

此时容器内未安装openssh,因此我们首先要安装openssh

1
2
3
apt-get update
apt-get install -y openssh-server
apt-get install -y vim

2.2 设定密码

稍后我们要进行密码登录,所以这里设置一下密码

1
2
3
4
root@ee767b7c05d6:/workspace# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

2.3 设置密码登录

默认的,openssh不允许密码登录,这里我们设置一下

1
vim /etc/ssh/sshd_config

将其中的PasswordAuthentication后面改为yes

然后重启openssh

1
service ssh restart

就可以按照秘钥登录所述ssh登录docker了,注意如果不修改PasswordAuthentication的话登录后输入密码会被docker拒绝登录Permission denied, please try again.