Package: reacher
ReacherFrom your local machine, ReacherDocker will,build a docker image on the remote (docker must already be installed and ssh enabled) according to specificationsset up container on the remote with port port-forwarding and enviroment variablesexecute your local code on the remote, in the container, with printouts shown as your were running it locallyupload/download files from the container to your local machineand for your local machine, Reacher will,execute your local code on the remote, with printouts shown as your were running it locallyupload/download files from the remote to your local machineGetting started...To get started,pipinstallreacher
pipinstallpython-dotenvFirst we must setup a connection to the remote, RemoteClient will create a ssh connection between the local and remote machine.fromreacher.reacherimportReacher,ReacherDocker,RemoteClientfromdotenvimportdotenv_valuesconfig=dotenv_values()# take environment variables from .env.client=RemoteClient(host=config["HOST"],user=config["USER"],password=config["PASSWORD"],ssh_key_filepath=config["SSH_KEY_PATH"])the connection is sent to ReacherDocker together with the name of the image that we want to build and the name of the container.reacher=ReacherDocker(client=client,build_name="base",image_name="base",build_context="dockercontext",)or send in the aruments for RemoteClient direcly to Reacherreacher=ReacherDocker(client=client,build_name="base",image_name="base",build_context="dockercontext",host=config["HOST"],user=config["USER"],password=config["PASSWORD"],ssh_key_filepath=config["SSH_KEY_PATH"])build_context should contain everything for building the docker image on the remote. It might look like,$lsdockercontext/
Dockerfilerequirements.txtOnce ReacherDocker has been setup we can build the image on the remote. ReacherDocker will send the build_context to the remote and
trigger docker to build an image according to the specifications in the Dockerfilereacher.build()[+]Building0.0s(0/1)[+]Building0.2s(2/3)=>[internal]load.dockerignore0.0s=>=>transferringcontext:2B0.0s=>[internal]loadbuilddefinitionfromDockerfile0.0s=>=>transferringdockerfile:528B0.0......and thereafter we can setup the docker container. Reacher will make sure this container is running until we have explicitly deleted it.reacher.setup(ports=[8888,6666],envs=dotenv_values(".env"))If you want to execute the code direcly on the remote, not in a container, go for Reacher. Reacher will use the remote enviroment, as is, when executing the commands.reacher=Reacher(build_name="base",host=config["HOST"],user=config["USER"],password=config["PASSWORD"],ssh_key_filepath=config["SSH_KEY_PATH"],prefix_cmd="PATH=....")prefix_cmdis useful to set when we want to specify some PATH or when we want to source an venv before running a command.Port-forwarding between remote and localIf you want to access some service on the remote, you can forward the traffic on the ports of the remote to the local machine.reacher.add_port_forward(remote_port=6006,local_port=5998,paramiko=True)this will spin of a seperate daemon thread handling the port-forwading. Set paramiko to False to trigger a system call for the port forwarding instead.Put and getting filesSupports list of files or single filesreacher.put(["setup.py","build.sh","reacher"],<destination>)default destination is root directory of the build.reacher.get(["setup.py","build.sh","reacher"],<destination>)default destination is.reacher/build_name, relative your local path.Usereacher.ls(base_path)to list files on the remote.Running commands on the remotereacher.execute_command("ls",wrap_in_screen=True,named_session="test")wrap the command in a screen if running something that you want make persistent. If named_session is not specified an unique id will be created for the sesssion.reacher.list_named_sessions()will list current sessions andreacher.kill_named_sessions(<session_name>)will kill the selected session.Running code on the remoteRunning a code-snippetNow we have built the docker image on the remote and have a container ready to execute whatever code that we want to run.A "Hello World" test can be triggered from a notebook.First we create the python module that we want to execute,%%writefilesimple_test.pyimporttimewhile1:print("Hello from remote")time.sleep(1)and then we execute it on the remote inside our controlled docker enviroment.reacher.execute(command="python simple_test.py",context=["simple_test.py"],named_session="simple_test",# clean the container from previous runs.cleanup_before=True,wrap_in_screen=True,)HellofromremoteHellofromremote...simple_test will continue to run in the background (even if you kill the cell/script that you instantiated the reacher.execute from) until we explicitly have killed it.With list_named_sessions you can get all currently running sessions.reacher.list_named_sessions()Thereisascreenon:22.simple_test(03/19/2318:20:07)(Attached)1Socketin/run/screen/S-root.we can always attach to a named session to continue to get printouts.reacher.attach_named_session("simple_test")or kill itreacher.kill_named_session("simple_test")Running with dependenciesTo execute some code that depends on other modules inside a src directory, simply add src as a context_folder when calling
reacher.execute.%%writefiledependency_test.pyfromdependencyimportDependencyd=Dependency()reacher.execute(command="python dependency_test.py",context=["src","dependency_test.py"],named_session="dependency_test",)HellofromclassDependency[screenisterminating]