文章目录
- 一: 利用 Docker 镜像搭建
- 1.编写 Dockerfile
- 2.构建并配置 Remote Interpreters
- 3.结论
- 0.FAQ
- 二: 利用 SSH + Docker 镜像搭建
- 1.编写 Dockerfile
- 2.构建并运行
- 3.构建镜像
- 4.运行容器
- 5.验证并配置
- 0.FAQ
起因是需要在 M2 芯片的 Mac 上调试基于 Python3.6.1 构建的程序. 而 MacOS预装的是 3.9 的 Python, 为了更好的做环境隔离以及屏蔽特定宿主机 (如 Mac M1/M2 芯片的宿主机) 与特定 Python 版本及其依赖包的版本差异问题, 想着利用 PyCharm 提供的 “连接 Docker 容器中的” 或是 “SSH 到远端 ‘环境机’ 中的” Python Interpreters 特性, 将环境运行在 “Rmeote Intepreters” 中.
主要方式也有二:
- 要么是直接将环境运行在 Docker 中, 用 PyCharm 的 Docker Intepreter 连接;
- 要么是将环境运行在以 SSH Intepreter 中, PyCharm 通过 SSH 连接远端运行有 Python3.6.1 的服务, 通过将代码上传至远端服务的方式运行 Py 程序;
简单而快速的记录, 涵盖一些过程中的一些注意点. 将分别介绍这两种实现方式. 首先是环境:
- Python 版本: 3.6.1
- PyCharm 版本: latest
- Docker
- Hub: 本文相关镜像已上传的 Hub, 点击前往
一: 利用 Docker 镜像搭建
镜像已经推到 Hub, 直接拉下来即可: docker pull caplike/python:v3.6.1
1.编写 Dockerfile
FROM rockylinux:8
MAINTAINER like ""
ARG PYTHON_VERSION=3.6.1
# install related packages
RUN cd / && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& yum makecache \
&& yum install -y wget xz zlib* automake autoconf make gcc gcc-c++ libffi-devel epel-release which \
&& yum clean all
# install version-compatible openssl
RUN wget https://www.openssl.org/source/openssl-1.0.2h.tar.gz \
&& tar zxf openssl-1.0.2h.tar.gz && rm -rf openssl-1.0.2h.tar.gz \
&& cd openssl-1.0.2h \
&& ./config --prefix=/usr/local/openssl-1.0.2 no-zlib \
&& make && make install
# install python 3.6.1
RUN wget https://npm.taobao.org/mirrors/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz \
&& tar -xvf Python-${PYTHON_VERSION}.tar.xz -C /usr/local/ \
&& rm -rf Python-${PYTHON_VERSION}.tar.xz \
&& cd /usr/local/Python-${PYTHON_VERSION}
COPY Setup /usr/local/Python-3.6.1/Modules
RUN cd /usr/local/Python-${PYTHON_VERSION} \
&& ./configure && make && make install
COPY requirements.txt /
# install related packages
RUN yum install -y python3-pip \
&& pip3 install -i https://pypi.doubanio.com/simple/ -r /requirements.txt
其中,
- 第一层 RUN 主要是为了编译 Python3.6.1, 安装需要的包.
- 第二层 RUN 是为了解决特定版本的 Python 与 openssl 兼容性问题 (Can’t connect to HTTPS URL because the SSL module is not available), 这里经过反复调试选择了 openssl-1.0.2h 这个版本. 同时需要修改 Python Modules 的 Setup 文件内容以指定该版本的 openssl, 修改的地方是:
- 第三层 RUN 负责编译安装 Python3.6.1
- 最后一部分则是预装 pip3 以及外置 requirements.txt 中的包
2.构建并配置 Remote Interpreters
# build image
docker build -t caplike/python:v3.6.1 .
构建镜像并启动容器后, 在 PyCharm 中配置即可. 随后 PyCharm 就会尝试基于该镜像启动容器来运行 Py 程序.
3.结论
这种方式有一个我认为非常致命的问题, 那就是需要在容器构建前提前安装好依赖,不然后续没法安装(因为后续是基于容器运行的镜像,执行完命令就没了). 还是比较耗时, 且编译过程也远远谈不上 “流畅”.
下一个方案: 还是需要通过 SSH 服务保证 Docker 镜像常驻。这样才能保证依赖包的实时安装。
0.FAQ
- There was a problem confirming the ssl certificate: Can’t connect to HTTPS URL because the SSL module is not available.
需要安装 openssl - pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.
openssl 与 python 的版本不兼容导致: https://www.cnblogs.com/fcc-123/p/12021104.html#circle=on
二: 利用 SSH + Docker 镜像搭建
利用 PyCharm 基于 SSH Intepreter (Python3.6.1 的环境运行于其中) 实现的 Python 环境调试.
镜像已经推到 Hub, 直接拉下来即可: docker pull caplike/python:v3.6.1-ssh
1.编写 Dockerfile
在第一种方式的基础上, 制作包含 ssh 服务的 docker 镜像. 具体方式是在 Dockerfile 中构建完 Python3.6.1 相关环境后, 再进行 ssh 的安装和初始化工作.
FROM rockylinux:8
MAINTAINER like ""
ARG PYTHON_VERSION=3.6.1
ARG PYTHON_HOME=/usr/local/Python-${PYTHON_VERSION}
ARG PYTHON_LIB_DIRECTORY=/usr/local/lib/python3.6
ARG SSH_USERNAME=caplike
ARG SSH_USERPASS=218114
# install openssh-server & passwd
# rsync: pycharm required
RUN yum install -y openssh-server passwd rsync \
&& useradd ${SSH_USERNAME} \
&& echo -e "$SSH_USERPASS" | passwd --stdin ${SSH_USERNAME} \
&& echo ssh username: ${SSH_USERNAME} && echo ssh userpass: ${SSH_USERPASS} \
&& ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key \
&& ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key \
&& ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
EXPOSE 22
ENTRYPOINT ["/usr/sbin/sshd", "-D"]
# install related packages
RUN cd / && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& yum makecache \
&& yum install -y wget xz zlib* automake autoconf make gcc gcc-c++ libffi-devel epel-release which \
&& yum clean all
# install version-compatible openssl
RUN wget https://www.openssl.org/source/openssl-1.0.2h.tar.gz \
&& tar zxf openssl-1.0.2h.tar.gz && rm -rf openssl-1.0.2h.tar.gz \
&& cd openssl-1.0.2h \
&& ./config --prefix=/usr/local/openssl-1.0.2 no-zlib \
&& make && make install
# install python 3.6.1
RUN wget https://npm.taobao.org/mirrors/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz \
&& tar -xvf Python-${PYTHON_VERSION}.tar.xz -C /usr/local/ \
&& rm -rf Python-${PYTHON_VERSION}.tar.xz \
&& cd ${PYTHON_HOME}
COPY Setup ${PYTHON_HOME}/Modules
RUN cd ${PYTHON_HOME} \
&& ./configure && make && make install
# install pip3
RUN yum install -y python3-pip
RUN chown -R ${SSH_USERNAME}:${SSH_USERNAME} ${PYTHON_LIB_DIRECTORY} \
&& rm -rf /run/nologin
2.构建并运行
3.构建镜像
docker build -t caplike/python:v3.6.1-ssh .
4.运行容器
sh run_container_python3.6.1.sh
#!/bin/bash
#description: run container of python3.6.1 and ssh.
#author: like
#date: 2023-05-01
docker run -d -p 20007:22 \
--name env-python3.6.1-ssh \
--restart=always \
caplike/python:v3.6.1-ssh
5.验证并配置
SSH 到本机容器成功:
并且, 通过 PyCharm 的 SSH Intepreter 连接也是成功:
0.FAQ
-
Unable to load host key
sshd 守护进程不能加载主机秘钥文件.
需要生成主机秘钥文件, 在 Dockerfile 倒数第二层末尾追加:
&& ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
&& ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
&& ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -
System is booting up. Unprivileged users are not permitted to log in yet
在 Dockerfile 末尾新增: RUN rm -rf /run/nologin -
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
此报错是由于远程的主机的公钥发生了变化导致的。
ssh 服务是通过公钥和私钥来进行连接的,它会把每个曾经访问过计算机或服务器的公钥(public key),记录在~/.ssh/known_hosts 中,当下次访问曾经访问过的计算机或服务器时,ssh 就会核对公钥,如果和上次记录的不同,OpenSSH 会发出警告。
清除本地 /Users/<用户名>/.ssh/known_hosts 对应 ip 的秘钥信息.