Skip to content

Instantly share code, notes, and snippets.

@RickyCook
Last active November 7, 2023 06:55
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save RickyCook/663b9f4ae53d454f73bf to your computer and use it in GitHub Desktop.
Save RickyCook/663b9f4ae53d454f73bf to your computer and use it in GitHub Desktop.
Using socat to forward new ports via STDIO in a running Docker container

What?... Why?

Imagine you're messing around in a container, and you install some stuff, add some config, and now it's time to load up your client and check it out! Oh wait, you forgot to forward ports when you created the container! Fear not, all is not lost, for in the world of pipes, and streams, there is always a way to do something disgusting.

The Dockerfile

Example Dockerfile included will install Nginx, and socat in a container, and make Nginx run in foreground mode. To build, and run:

docker build .
docker run -it --name socat-nginx <image_id>

This will give you a container running Nginx on port 80, but with no forwarded ports.

The awful socat one-liner

I'll just get right into it. Forgive me:

socat TCP-LISTEN:8080,reuseaddr,fork 'EXEC:docker exec -i socat-nginx "socat STDIO TCP-CONNECT:localhost:80"'

So what's this doing?

  • TCP-LISTEN:8080: socat running locally will accept connections of port 8080
  • reuseaddr,fork: When accepting a connection, socat will fork to handle it. This means that it can handle parallel connections, and won't die after the first connection
  • EXEC:...: Instructs socat to execute a command, and forward the accepted connection (in this case, our TCP-LISTEN) to the standard input/output. This will happen every time socat accepts a connection
  • docker exec -i socat-nginx: Execute a new command in our running container. -i lets Docker know that we want to immediately attach (formard stardard in/out/err)
  • socat STDIO: In the Docker container, run socat and accept standard input/output as the stream source
  • TCP-CONNECT:localhost:80: Open a connection to port 80 in the container, and stream stdin to it's write buffer. Socat will read, and stream from the port to stdout (which is passed back through Docker, to local socat, and out the TCP port we've given)
FROM alpine:3.2
RUN apk add --update nginx socat && \
rm -rf /var/cache/apk/*
RUN echo 'daemon off;' >> /etc/nginx/nginx.conf
CMD ["/usr/sbin/nginx"]
@nedix
Copy link

nedix commented Jul 10, 2018

This is worthless on it's own. What is socat-nginx, where did you include the Dockerfile?

@minskmaz
Copy link

minskmaz commented Nov 4, 2021

this is really awesome. thank you for sharing it!

@alexkunin
Copy link

Thanks, it helped alot. My use-case was connecting with chrome://inspect to a NodeJS instance running in a Docker container on a remote server.

@JackBailey
Copy link

Thank you this really helped - used it so I can forward plex (static on port 32400) to my gluetun container

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