Created
September 18, 2024 10:11
-
-
Save stefanpejcic/e6010daa77c5d6ef964ef61bfef40bb7 to your computer and use it in GitHub Desktop.
flask terminal for container - ispired by https://gist.github.com/Humerus/0268c62f359f7ee1ee2d
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from flask import Flask, render_template, request | |
from flask_socketio import SocketIO, emit | |
import docker | |
app = Flask(__name__) | |
socketio = SocketIO(app, cors_allowed_origins="*") | |
client = docker.from_env() | |
@app.route('/terminal/<container_id>') | |
def terminal(container_id): | |
try: | |
client.containers.get(container_id) | |
except docker.errors.NotFound: | |
return "Container not found", 404 | |
return render_template('terminal.html', container_id=container_id) | |
@socketio.on('connect') | |
def handle_connect(): | |
print('Client connected') | |
@socketio.on('disconnect') | |
def handle_disconnect(): | |
print('Client disconnected') | |
@socketio.on('input') | |
def handle_input(data): | |
container_id = data['container_id'] | |
command = data['command'].strip() | |
try: | |
container = client.containers.get(container_id) | |
exec_id = client.api.exec_create(container.id, cmd=['bash', '-c', command], tty=True, stdin=True, stdout=True, stderr=True) | |
output = client.api.exec_start(exec_id, detach=False, tty=True) | |
emit('output', {'data': output.decode('utf-8')}) | |
except docker.errors.NotFound: | |
emit('error', {'message': 'Container not found'}) | |
except Exception as e: | |
emit('error', {'message': str(e)}) | |
if __name__ == '__main__': | |
socketio.run(app, host='0.0.0.0', port=5000, debug=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Web Terminal</title> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm/css/xterm.css" /> | |
<style> | |
#terminal { | |
width: 100%; | |
height: 500px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Terminal for Container: {{ container_id }}</h1> | |
<div id="terminal"></div> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/xterm.min.js"></script> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/xterm-addon-fit.min.js"></script> | |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/xterm.css" /> | |
<script src="https://cdn.socket.io/4.6.1/socket.io.min.js"></script> <!-- Ensure you use the latest version or the version compatible with your server --> | |
<script> | |
const terminal = new Terminal(); | |
const fitAddon = new FitAddon.FitAddon(); | |
terminal.loadAddon(fitAddon); | |
terminal.open(document.getElementById('terminal')); | |
fitAddon.fit(); | |
const socket = io.connect('http://165.232.70.181:5000'); // Update this URL if needed | |
let currentCommand = ''; | |
terminal.onData(data => { | |
// Handle special keys | |
if (data === '\r') { | |
// Enter key pressed, send the command | |
socket.emit('input', { container_id: '{{ container_id }}', command: currentCommand }); | |
currentCommand = ''; // Reset for the next command | |
} else if (data === '\x7f') { | |
// Backspace key pressed | |
currentCommand = currentCommand.slice(0, -1); | |
terminal.write('\b \b'); // Erase last character | |
} else if (data === '\x1b[D') { | |
// Left arrow key (could be handled differently based on actual escape sequences) | |
terminal.write(data); // Placeholder for cursor movement | |
} else if (data === '\x1b[C') { | |
// Right arrow key (could be handled differently based on actual escape sequences) | |
terminal.write(data); // Placeholder for cursor movement | |
} else { | |
// Append data to command and write to terminal | |
currentCommand += data; | |
terminal.write(data); | |
} | |
}); | |
socket.on('output', (data) => { | |
terminal.write(data.data); | |
}); | |
socket.on('error', (data) => { | |
terminal.write('\r\nError: ' + data.message); | |
}); | |
socket.on('connect', () => { | |
console.log('WebSocket connected'); | |
}); | |
socket.on('disconnect', () => { | |
terminal.write('\r\nConnection closed.'); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment