I’m not sure how common this technique is. I described the why I use unix sockets with my docker apps in my last post Why I build my Custom Images.
Let’s talk about the how
I’ll start with an easy example. Let’s find an image that exposed a port. I’ll go with Glances.
Modifying the Configs
To expose your app over a socket instead you will need to use a reverse proxy inside
the container. Which means you will have 2 running processes, the proxy and in our
case the glances app. I use s6-overlay
but you can use quite literally
whatever you’re comfortable with. But this is what the Dockerfile would look like.
FROM nicolargo/glances:latest-full
ADD https://github.com/just-containers/s6-overlay/releases/download/v2.2.0.3/s6-overlay-amd64-installer /tmp/
RUN chmod +x /tmp/s6-overlay-amd64-installer
COPY --from=caddy:latest /usr/bin/caddy /usr/bin/caddy
RUN /tmp/s6-overlay-amd64-installer /
COPY etc/services.d /etc/services.d
COPY Caddyfile /Caddyfile
ENV S6_SYNC_DISKS=1
CMD ["/init"]
You could use something lighter than Caddy but we’re not concerned with that here.
To actually run the services together we will follow the s6-overlay way of creating
etc/services.d/{service_name}/run
files for Caddy and Glances and then
copying them to the container. (see Dockerfile above)
{glances_path_on_my_host_machine}etc/services.d/caddy/run
#!/usr/bin/with-contenv sh
caddy run --config=/Caddyfile
{glances_path}/etc/services.d/glances/run
#!/usr/bin/with-contenv sh
cd /app
/venv/bin/python3 -m glances -C /etc/glances.conf $GLANCES_OPT
Here’s what my Caddyfile will look like {glances_path}/Caddyfile
http:// {
bind unix//sockets/glances.sock
reverse_proxy localhost:61208
}
61208
is what Glances runs at. Now in my docker compose I would do
something like:
version: '3'
services:
glances:
- image: nicolargo/glances:latest-full
+ build:
+ context: .
+ dockerfile: Dockerfile
restart: unless-stopped
- ports:
- - '127.0.0.1:61208-61209:61208-61209'
environment:
- TZ=${TZ}
- GLANCES_OPT=-w
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /run/user/1000/podman/podman.sock:/run/user/1000/podman/podman.sock:ro
+ - ./sockets/:/sockets
pid: host
Glances will run over a UDS stored in
{glances_path}/sockets/glances.sock
and our container doesn’t expose any
ports!
Now, the last thing we gotta do is to make sure my Tailnet can still access glances. So in my Caddyfile, I’ll make the following changes.
glances.example.com {
- reverse_proxy localhost:61208
+ reverse_proxy unix//{glances_path}/sockets/glances.sock
}
Note
Caddy’s syntax for UDS is
unix//
+<path to .sock>