How to connect to a docker container from web? - docker

I am working on a new project where I need to connect to a docker container from web?
By connect I mean I will create a shell in the website and tat shell will be able to connect to the running container.
I am not able to figure out how to proceed with the project.
Can anyone help me out?

From what I know there is no out of the box solution, you should make your own api executing command on your container running docker exec <id> <command> and returning the output, mind escape the command.
However you should know that letting a user run commands inside a docker is dangerous as it could impact your host.

You should be able to use Docker APIs for this (https://docs.docker.com/engine/api/) along with a framework that wraps the APIs. For example refer dockerode.

You could combine some JavaScript modules. node-pty and xterm being the most important. Additionally, ws is useful, but could be replaced but something else.
Note: this is not a production ready example. In particular, you should take care of safety measurements, or better yet, let no one but yourself use it.
server.js
import { WebSocketServer, createWebSocketStream } from 'ws';
import pty from 'node-pty';
const wss = new WebSocketServer({ port: 3000 });
wss.on('connection', (ws) => {
console.log('new connection');
const duplex = createWebSocketStream(ws, { encoding: 'utf8' });
const proc = pty.spawn('docker', ['run', "--rm", "-ti", "ubuntu", "bash"], {
name: 'xterm-color',
});
const onData = proc.onData((data) => duplex.write(data));
const exit = proc.onExit(() => {
console.log("process exited");
onData.dispose();
exit.dispose();
});
duplex.on('data', (data) => proc.write(data.toString()));
ws.on('close', function () {
console.log('stream closed');
proc.kill();
duplex.destroy();
});
});
index.html
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="node_modules/xterm/css/xterm.css" />
<script src="node_modules/xterm/lib/xterm.js"></script>
</head>
<body>
<div id="terminal"></div>
<script type="module">
const term = new Terminal();
term.open(document.getElementById('terminal'));
const ws = new WebSocket('ws://localhost:3000');
ws.onmessage = async ({ data }) => term.write(await data.text());
term.onData((data) => ws.send(data));
</script>
</body>
</html>
Note: I am using the statics from the node modules folder, in your real code you probably want to use a bundler for this.
I am serving the entire project with nginx on port 8080 for simplicity. And then I start the server with node.
docker run -d --rm -p 8080:8080 -v "$PWD:/usr/share/nginx/html" nginxinc/nginx-unprivileged
node server.mjs
Afterwards, I can open http://localhost:8080 in my browser, and get a shell.
The dependencies in my package.json are these:
"dependencies": {
"node-pty": "^0.10.1",
"ws": "^8.7.0",
"xterm": "^4.18.0"
}
You can view the code in this repo: https://github.com/bluebrown/web-shell.

Related

Chainlink Hackathon 21 HardHat tutorial execute function in Smart Contract

I would put this on stack overflow but it's specific to the hackathon. This is for the HardHat tutorial. I am trying to execute my get-number function on my smart contract. My contract is deployed. This is my command: npx hardhat get-number --contract 0x5FbDB2315678afecb367f032d93F642f64180aa3. This is the error I get: Error: call revert exception (method="getNumber()", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.5.0). Any thoughts would help...Thanks.
Here is the Task
task("get-number", "Reads the number")
.addParam("contract", "The contract's address")
.setAction(async (taskArgs) => {
const contractAddr = taskArgs.contract;
const MyFirstContract = await ethers.getContractFactory('MyFirstContract');
const accounts = await ethers.getSigners();
const signer = accounts[0];
const myFirstContract = await new ethers.Contract(contractAddr, MyFirstContract.interface, signer);
let result = BigInt(await myFirstContract.getNumber()).toString();
console.log('Stored number is: ' + result);
});
module.exports = {};
I had similar error when following along with this hackathon tutorial.
My fix was to specify the --network when executing my task, get-number. So, in your example:
npx hardhat get-number --network localhost --contract 0x5FbDB2315678afecb367f032d93F642f64180aa3
This will execute the task using the Hardhat network the demo instructed you to start when you ran npx hardhat node
Hardhat Network doc
See Running Stand-Alone doc
I asked on the hackathon Discord why the demo didn't pass this, yet still worked, but haven't yet received an answer.
I have the same problem, and the way I fixed it is to start hardhat with npx hardhat node --hostname 0.0.0.0 instead of npx hardhat node
You'll need to deploy the contract to localhost as well: npx hardhat run scripts/deploy.js --network localhost
Then using npx hardhat --network localhost to call the 2 functions.

Laravel 8 jetstream hot reload and browser sync do not work

I have a big problem with a system I just created.
I did the standard installation of Laravel 8 with jetstream using the docker and laravel sail...
However, I am not able to do the npm run hot or npm run watch to auto reload or browser sync...
My files are standard with laravel 8 and I haven't made any changes to the code yet.
Informations:
Laravel: v8.41.0
PHP: PHP v8.0.5
Jetstream: v2.3.5
npm: v7.7.6
NodeJS: v15.14.0
my webpack.mix.js looks like this:
const mix = require('laravel-mix');
/*
|--------------------------------------------------------------------------
| Mix Asset Management
|--------------------------------------------------------------------------
|
| Mix provides a clean, fluent API for defining some Webpack build steps
| for your Laravel applications. By default, we are compiling the CSS
| file for the application as well as bundling up all the JS files.
|
*/
mix.js('resources/js/app.js', 'public/js').vue()
.postCss('resources/css/app.css', 'public/css', [
require('postcss-import'),
require('tailwindcss'),
])
.webpackConfig(require('./webpack.config'));
if (mix.inProduction()) {
mix.version();
}
my webpack.config.js looks like this:
const path = require('path');
module.exports = {
resolve: {
alias: {
'#': path.resolve('resources/js'),
},
},
};
I have also tried to change the two webpacks with some information I found earlier in research, but really nothing is working, would there be a way for Hot Reload and Browser Sync to work together with Laravel Sail?
While a browsersync script is already included in app.blade.php I did not get it to work either. I removed that line and expanded my webpack.mix.js as follows:
mix.browserSync({
proxy: 'YOURDOMAIN.test',
host: 'YOURDOMAIN.test',
open: 'external'
});
Then run npm run watch- probably twice because it's going to install browsersync - and it's working.
open: 'external' save me ( same i use valet and https )
.browserSync({
proxy: 'https://app.tunnel.test',
host: 'app.tunnel.test',
open: 'external',
https: {
key: homedir + '/.config/valet/Certificates/' + domain + '.key',
cert: homedir + '/.config/valet/Certificates/' + domain + '.crt',
},
})

Gatsby .env.production variables - undefined

When building a Gatsby project I'm getting all env variables undefined in production environment.
In development everything is fine.
I have 2 similar .env.development and .env.production files.
In my gatsby-config.js I have
require('dotenv').config({
path: `.env.${process.env.NODE_ENV}`,
});
and if I console.log(process.env.NODE_ENV) during gatsby build it gives production and the variables can be accessed and logged out.
But later in code something like
return request.post(`${process.env.GEOCODING_CF_URL}/latlng`, {...});
gives request to http://localhost:9000/ru/undefined/latlng.
What am I doing wrong and how this issue can be fixed?
UPDATE:
When I run gatsby build - process.env.NODE_ENV is production
When I run gatsby serve - process.env.NODE_ENV is undefined
If this can help in any way.
If you use environment variables in node you don't need a prefix (like in your gatsby-config.js). However, if you need to use them in a component or a page you must add GATSBY_ as a prefix, so GEOCODING_CF_URL should be GATSBY_GEOCODING_CF_URL
For me, NODE_ENV=production yarn gatsby serve did the trick.
https://www.gatsbyjs.com/docs/how-to/local-development/environment-variables/
Accessing Environment Variables in the browser.
By default, environment variables are only available in Node.js code and are not available in the browser as some variables should be kept secret and not exposed to anyone visiting the site.
To expose a variable in the browser, you must preface its name with GATSBY_. So GATSBY_API_URL will be available in browser code but API_KEY will not.
Variables are set when JavaScript is compiled so when the development server is started or you build your site.
src/pages/index.js
Copysrc/pages/index.js: copy code to clipboard
import React, { useState, useEffect } from "react"
function App() {
const [data, setData] = useState()
useEffect(async () => {
const result = await fetch(
`${process.env.GATSBY_API_URL}/users`
).then(res => res.json())
setData(result.data)
})
return (
<ul>
{data.map(user => (
<li key={user.id}>
<a href={user.url}>{user.name}</a>
</li>
))}
</ul>
)
}
export default App

BrowserWindow in electron does not open

I just tried to test electron environment for programming with JavaScript on desktop with Windows 10.
So I have an app:
const electron=require("electron");
const app=electron.app;
const BrowserWindow=electron.BrowserWindow;
var mainWindow=null;
app.on("ready",function(){
mainWindow=new BrowserWindow({height:600,width:800});
mainWindow.loadURL("file://"+__dirname+"index.html");
});
and index.html is:
<html>
<head>
<title> MyIndex.html </title>
</head>
<body>
Hello World from Electron!<br>
</body>
</html>
and package.json is:
{
"name":"Electron-Test",
"version":"0.1.0",
"main":"./main.js",
"scripts":{"start":"electron ."}
}
If I run electron . or npm start the application seems to start, but no browser window opens. On console I have to press Ctrl-C to stop the application.
Does anyone know where is the problem?
try to add one more/after file:
you are also missing a / before index.html
app.on("ready",function(){
mainWindow=new BrowserWindow({height:600,width:800});
mainWindow.loadURL("file:///"+__dirname+"/index.html");
});
i saw it in this video, at 3:32 https://www.youtube.com/watch?v=i0AkgNv4U4E

React Native Socket.io How to Connect to Local Node Server from Device

I'm making a connection when pointing the io.connect() method towards my localhost in the iOS simulator, so everything is working there.
But when the connect() method is pointed towards my machine's LAN IP address I am unable to successfully connect to the server neither in the simulator or on the device..
I'm pretty stumped on this one right now, any help would be appreciated thanks.
Solved by tunneling localhost:3000 via ngrok and allowing an exception domain.
In your info.plist you need the following under App Transport Security Settings
On a mac command line run
brew cask install ngrok
ngrok http 3000
Then grab the outputted ngrok.io URL and use it in your io.connect() call and you should be set.
Simple way -> Connection with Socket.io to Local Node Server:
First Step : you need to install socket.io into your project -
npm install socket.io-client
or
yarn add socket.io-client
App.js file :
import { io } from "socket.io-client";
const socketIOConnectionWithLocalhost = () => {
var socket = io('localhost:3000', { jsonp: false });
console.log('socket: ', socket);
socket.on('connect', () => {
console.log("socket connected...");
})
socket.on("update", () => {
console.log('App.js : socket event recieved:');
});
};
Second Step : create server folder and inside it create two files: app.js and index.html (As per given in below image)
Server/app.js File :
var express = require('express');
var app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('server - app.js - socket.id: ', socket.id);
socket.on('update', (data) => {
console.log('server - app.js - update:', data);
io.emit('update', socket.id)
});
});
app.get('/', function (req, res) {
res.sendFile(__dirname + '/index.html');
});
server.listen(3000);
index.html file :
<h1>Welcome To Server</h1>
<button>UPDATE</button>
<script src="/socket.io/socket.io.js"> </script>
<script>
var socket = io();
var button = document.querySelector('button');
button.onclick = function(){
console.log('index.html - buttion click...')
socket.emit('update');
}
</script>
Third Step : To start node server using below command:
first go to inside server folder then enter below command -> cd Server
node app.js
Then open any browser and hit localhost url -> http://localhost:3000/
Thanks..!

Resources