devcontainers / devcontainers/features

docker-outside-of-docker: socat breaks interactive support

Open
#483 4 comments 3 reactions 1 assignee Claimed by @alexander-smolyakov View on GitHub
Dominant language
Shell
Stars
1.5k
Forks
621
Avg merge
2d 11h
Merged PRs (30d)
4

Description

When docker-outside-of-docker feature ends up using `socat` to create a Unix socket ready to use by user in container, you will experience the following inside your terminal:

1. `echo "uname; exit 1" | docker run --interactive ubuntu:jammy` will work as expected:
* will otuput `Linux`
* will exit with code 1
2. `echo "sleep 2; uname; exit 2" | docker run --interactive ubuntu:jammy` won't work as expected:
* won't output Linux (output lost)
* exit code will correctly be 2
3. `(echo "sleep 2; uname; exit 2"; sleep 3) | docker run --interactive ubuntu:jammy` will work as expected

This can be reproduced out of devcontainer context by starting `socat`:
```shell
# start socat
socat UNIX-LISTEN:$HOME/docker.sock,fork,reuseaddr UNIX-CONNECT:/var/run/docker.sock &

# using our new docker socket
export DOCKER_HOST=unix://$HOME/docker.sock
```

I had to dig deep but socat manual got the answer:
> -t
> When one channel has reached EOF, the write part of the other channel is shut down. Then, socat waits [timeval] seconds before terminating. De‐
> fault is 0.5 seconds. This timeout only applies to addresses where write and read part can be closed independently. When during the timeout interval the
> read part gives EOF, socat terminates without awaiting the timeout.

Without tuning `socat -t xxx`, it will close connection after 0.5s all stdin data has been sent. docker client will then wait for container to get its exit code but will never received the subsequent output. Tuning that timeout can be a nightmare since it has to be more than the longest pause in output data.

Best is to get rid of socat and rely on group membership:
* this feature mostly tries to adjust docker's group id to match the one of the docker host socket: i believe this is wrong since files in container may belong to that group and won't be adjusted accordingly
* i would instead:
* get group id of the docker host socket
* locate group using that id and if none is found create one (e.g. docker-host or devc-docker-host to ensure no name conflict can raise)
* add user to the group

I can help if needed.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.