成功最有效的方法就是向有经验的人学习!

django实现web端登录docker

功能主要通过 channels 提供 websocket 以及 docker-py 提供的API操作 docker
实现方法与 web 端登录普通主机基本一致

准备
已经安装好 django
已经安装配置好 channels:https://channels.readthedocs.io/en/latest/installation.html
已经安装好 docker-py:https://github.com/docker/docker-py

开始
以下内容均为了简单实现,实际上线可能需要修改部分内容

编写核心实现 docker_ssh.py

# -*- coding: utf-8 -*-

import docker
import threading
from socket import timeout
from channels.generic.websocket import WebsocketConsumer

您暂时无权查看此隐藏内容!
# 设置如果3分钟没有任何输入,就断开连接 self.tty._sock.settimeout(60 * 3) self.t1.setDaemon(True) self.t1.start() def receive(self, text_data=None, bytes_data=None): self.tty._sock.send(text_data.encode('utf-8')) def disconnect(self, close_code): try: self.tty._sock.close() self.client.close() finally: self.t1.stop()

编写 websocket 路由 routing.py

# -*- coding: utf-8 -*-

from django.urls import path
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from assets.utils.docker_ssh import DockerConsumer

application = ProtocolTypeRouter({

    "websocket": AuthMiddlewareStack(
        URLRouter([
            ...
            path(r'ws/dockerssh/', DockerConsumer),
           ...
        ]),
    ),
})

编写前端展示页 docker_terminal.html

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Docker</title>
    <link href="{% static 'css/xterm.css' %}" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="terms"></div>
</body>

<script src="{% static 'js/xterm.js' %}"></script>

<script>
    let cols = get_term_size().cols;
    let rows = get_term_size().rows;
    let ws_scheme = window.location.protocol === "https:" ? "wss" : "ws";
    let socket = new WebSocket(ws_scheme + '://' + window.location.host + '/ws/dockerssh/');

    let term = new Terminal({
        screenKeys: true,
        useStyle: true,
        cursorBlink: true,
        cols: cols,
        rows: rows
    });

    socket.onopen = function () {
        term.open(document.getElementById('terms'), true);
    };

    term.on('data', function (data) {
        socket.send(data);
    });

    socket.onmessage = function (msg) {
        term.write(msg.data);

    };
    socket.onerror = function (ev) {
        console.log('error', ev);
        document.getElementById('terms').innerHTML = '<h3>连接失败!</h3>';
    };
    socket.onclose = function (e) {
        // pass
        console.log(e)
    };

    function get_term_size() {
        let init_width = 10;
        let init_height = 17;

        let windows_width = document.documentElement.clientWidth;
        let windows_height = document.documentElement.clientHeight;

        return {
            cols: Math.floor(windows_width / init_width),
            rows: Math.floor(windows_height / init_height) - 1,
        }
    }
</script>

</html>

编写 view.py

def docker_ssh(request):
    return render(request, 'assets/docker_ssh.html')

编写路由 urls.py

# -*- coding: utf-8 -*-

from django.urls import path
from assets import views

urlpatterns = [
    ...
    path(r'docker_ssh/', views.docker_ssh, name='docker_ssh'),
]

此时访问 /docker_ssh 路径就可以成功登录指定容器了

file

注意点
如果 redis 配置了密码,则在 settings.py 中 channel 的配置需要指定密码,比如:

CHANNEL_LAYERS = {
    "default": {
        # This example app uses the Redis channel layer implementation channels_redis
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            # "hosts": [('127.0.0.1', 7779)],    redis没有密码使用该配置
            "hosts": [("redis://:Zhang.123@127.0.0.1:7779/0")],
        },
    },
}

websocket 返回 1011 状态码问题
我遇到两种情况:

web 端能够建立连接,但不管是否输入指令,都会几秒钟之后自动断开连接,并返回 1011 状态码
原因:我的 redis 设置的密码,但是在 settings.py 中 channel 的配置 CHANNEL_LAYERS 没有配置密码
解决办法:取消 redis 密码或按照上面的配置修改 CHANNEL_LAYERS

web 端能够建立连接,如果不输入指定则一直保持连接,但只要一输入指定,连接就会立即断开,并返回 1011 状态码
原因:向 socket 发送的是字符串,应该发送的是字节数据
解决办法:将 self.tty._sock.send(text_data) 改为 self.tty._sock.send(text_data.encode('utf-8'))

内容查看本文隐藏内容查看需要消耗5土豆币,请先
土豆币按需购买,不退换,请考虑清楚后购买。
赞(1) 打赏
未经允许不得转载:陈桂林博客 » django实现web端登录docker

大佬们的评论 13

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #11

    shika

    5456459个月前 (03-24)回复
  2. #10

    参考一下,可看可以实现不,我加你好友了,以后相互学习

    笨笨9个月前 (03-15)回复
  3. #9

    试试看,学习了

    试试看9个月前 (03-14)回复
  4. #8

    试试看,学习了

    xdx91年前 (2021-09-27)回复
  5. #7

    试试看

    1年前 (2021-09-13)回复
  6. #6

    试试看,学习了

    stone1年前 (2021-08-03)回复
  7. #5

    看着不错学习一下

    wlbl2年前 (2021-04-06)回复
  8. #4

    我这是3.0的django 方便留个联系方式不

    demonlg2年前 (2021-02-09)回复
    • 博客右下角有QQ和微信,我还没有用到这么新,项目中的框架还是老一些的版本

      admin2年前 (2021-02-09)回复
  9. #3

    貌似不行 这个 是不是有版本要求

    demonlg2年前 (2021-02-08)回复
    • 可以的,你用哪个版本,建议用版本1

      admin2年前 (2021-02-09)回复
  10. #2

    很好!

    ymym2年前 (2021-01-15)回复
  11. #1

    学习

    lzq78952年前 (2021-01-14)回复

全新“一站式”建站,高质量、高售后的一条龙服务

橙子建站.极速智能建站8折购买虚拟主机

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏