Skip to content

Instantly share code, notes, and snippets.

@kkimdev
Created June 1, 2019 18:34
Show Gist options
  • Save kkimdev/534669eea45b856dbd523faba7f16c4a to your computer and use it in GitHub Desktop.
Save kkimdev/534669eea45b856dbd523faba7f16c4a to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
set -Eeuxo pipefail
# Usage example: ./docker_host_port_forward.bash start 4000 14000
# ./docker_host_port_forward.bash stop 4000 14000
# TODO: alpine/socat is not necessarily trustworthy. Find a better base image
# or build ourselves.
# TODO: If socat is not installed, it fails silently. We should let user know
# if it failed and why it failed.
case "$1" in
"start")
start-stop-daemon -obm -p "/var/run/m19g_docker_host_port_forward_$2_$3" --start --startas \
"$(which socat)" TCP-LISTEN:"$2",fork,reuseaddr "EXEC:docker run --net=host --rm -i alpine/socat \"STDIO TCP-CONNECT:127.0.0.1:$3\""
;;
"stop")
start-stop-daemon -om -p "/var/run/m19g_docker_host_port_forward_$2_$3" --stop --startas \
"$(which socat)" TCP-LISTEN:"$2",fork,reuseaddr "EXEC:docker run --net=host --rm -i alpine/socat \"STDIO TCP-CONNECT:127.0.0.1:$3\""
;;
*)
echo "Usage: start [local_port] [docker_host_port]"
echo " stop [local_port] [docker_host_port]"
exit 1
;;
esac
@andyz-dev
Copy link

Thanks for sharing. I am a bit confused on how we should apply this idea. Should we assume windows machine have 'start-stop-daemon' installed? It seems I am missing something there.

@kkimdev
Copy link
Author

kkimdev commented Jun 2, 2019

@andyz-dev

Actually, it will be too much work, and I can't think of a completely clean way. Anyways, here is the explanation:

Problem

DOCKER_HOST can be unix://, tcp://, fd://, or ssh:// https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-socket-option . Also, being able to connect to the Docker Daemon doesn't necessarily mean that other ports are accessible from the local machine. So just knowing the machine IP is not sufficient.

Solution (the above utility)

The only 100% guaranteed working communication with the Docker daemon's machine is through STDIO. The above utility pipes TCP using socat https://medium.com/@copyconstruct/socat-29453e9fc8a6

local TCP <-> STDIO <-> docker daemon machine's TCP

Solution in the context of k3d

  • If k3d wants to use the above script directly, it requires socat utility. I'm not sure if k3d wants to introduce that dependency requirement. But socat is just a socket to stdio redirection utility, probably it's possible to implement with Go, or perhaps there is a library already.
  • We should instruct kubectl to connect to the specified local port. And provide a way to control the port forwarding e.g., k3d port-forward start/stop. Again, that's an additional burden to users that's not ideal.

@kkimdev
Copy link
Author

kkimdev commented Jun 2, 2019

Maybe we can provide a wrapper that does port-forwarding behind k3d kubectl or k3dctl. It doesn't seem too bad to me. microk8s also provides their own wrapper for example.

https://microk8s.io/docs/

microk8s.kubectl get nodes
microk8s.kubectl get services

@andyz-dev
Copy link

It seems I have made a mistake in leaving the above comment. My intention was to leave it under the thread of your review.

Thanks for the detailed explanation. They make sense to me. I am not familiar with the mirok8s project and it seems to be a good idea to take a look their design choices as well. Thanks for the pointers.

k3d project can definitely benefit more from your insights, suggestions and code contributions. Looking forward to them in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment