有没有一种Python本机方法可以通过ssh隧道将django连接到数据库?我见过有人在主机中使用 ssh 端口转发,但我更喜欢一个可以轻松容器化的解决方案。
非常无缝。
要求:
sshtunnel
包https://github.com/pahaz/sshtunnel
settings.py
中,在 django DB 设置块之前创建一个 ssh 隧道:from sshtunnel import SSHTunnelForwarder
# Connect to a server using the ssh keys. See the sshtunnel documentation for using password authentication
ssh_tunnel = SSHTunnelForwarder(
SERVER_IP,
ssh_private_key=PATH_TO_SSH_PRIVATE_KEY,
ssh_private_key_password=SSH_PRIVATE_KEY_PASSWORD,
ssh_username=SSH_USERNAME,
remote_bind_address=('localhost', LOCAL_DB_PORT_ON_THE_SERVER),
)
ssh_tunnel.start()
settings.py
中添加数据库信息块。在这里,我添加了一个默认的本地数据库和我们使用 ssh 隧道连接到的远程数据库DATABASES = {
'default': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'HOST': NORMAL_DB_HOST,
'PORT': NORMAL_DB_PORT,
'NAME': NORMAL_DB_NAME,
'USER': NORMAL_DB_USER,
'PASSWORD': NORMAL_DB_PASSWORD,
},
'shhtunnel_db': {
'ENGINE': 'django.contrib.gis.db.backends.postgis',
'HOST': 'localhost',
'PORT': ssh_tunnel.local_bind_port,
'NAME': REMOTE_DB_DB_NAME,
'USER': REMOTE_DB_USERNAME,
'PASSWORD': REMOTE_DB_PASSWORD,
},
}
就是这样。现在,可以使用
$ python manage.py migrate --database=shhtunnel_db
等命令迁移到远程数据库,或者使用 Models.objects.all().using('shhtunnel_db')
等行从 python 代码中调用数据库
额外: 就我而言,远程数据库是由其他人创建的,我只想读取它。为了避免编写模型并停用模型管理器,我使用以下 django 命令从数据库获取模型 [src]:
python manage.py inspectdb
是的,可以使用
sshtunnel
等库建立 SSH 隧道,随后修改 Django 的 settings.py
文件以在定义 DATABASES
之前使用此连接。您需要通过将 host 和 port 的值更改为 SSH 隧道绑定分配的值来实现此目的。
这是一个可用于通过 SSH 隧道测试数据库连接的脚本:
import os
import atexit
import pyodbc
from sshtunnel import SSHTunnelForwarder
ssh_tunnel = None
DB_DRIVER = ""
SSH_HOST = ""
SSH_PORT = ""
SSH_USER = ""
SSH_PASSWORD = ""
SSH_DB_NAME = ""
SSH_DB_USERNAME = ""
SSH_DB_PASSWORD = ""
SSH_DB_HOST = ""
SSH_DB_PORT = ""
try:
ssh_tunnel = SSHTunnelForwarder(
(SSH_HOST, int(SSH_PORT)),
ssh_username=SSH_USER,
ssh_password=SSH_PASSWORD,
remote_bind_address=(SSH_DB_HOST, int(SSH_DB_PORT)),
local_bind_address=("127.0.0.1", 0),
)
ssh_tunnel.start()
if ssh_tunnel.is_active:
print(f"SSH tunnel established: Local bind at {ssh_tunnel.local_bind_host}:{ssh_tunnel.local_bind_port}")
conn_str = (
f"DRIVER={DB_DRIVER};"
f"SERVER={ssh_tunnel.local_bind_host},{ssh_tunnel.local_bind_port};"
f"DATABASE={SSH_DB_NAME};"
f"UID={SSH_DB_USERNAME};"
f"PWD={SSH_DB_PASSWORD};"
)
try:
conn = pyodbc.connect(conn_str, timeout=30)
print("Connection successful!")
conn.close()
except pyodbc.Error as e:
print(f"Connection error: {e}")
else:
print("SSH tunnel could not be established.")
except Exception as e:
print(f"Error attempting to establish SSH tunnel: {e}")
def close_sshtunnel():
global ssh_tunnel
if ssh_tunnel and ssh_tunnel.is_active:
ssh_tunnel.stop()
print("SSH tunnel closed.")
atexit.register(close_sshtunnel)