简体   繁体   中英

Docker container not exiting when disconnected from a login shell

I have a docker container running on the server side as a user's login shell so that anyone can ssh into the server and get access to some resource inside.

Say, I have a user called test and I want people to be able to SSH into test 's account using some publicly available password. Here's what I have in /etc/passwd

test:1000:1000::/:/bin/test-shell

and in /bin/test-shell

#!/bin/bash
docker run -it --rm --network none python:3.10-alpine /bin/sh

Now, whenever someone ssh into my machine using ssh test@example.com , they are immediately dropped into a disposable docker container. So far so good.

The problem I have is, if the user doesn't exit the shell by either calling exit or pressing Ctrl-D but just closes their terminal window instead, the container is left running indefinitely and taking up limited server resources. I'm wondering if it is possible (and if so, how) to make sure the container is properly stopped (and therefore deleted) when a user disconnects.

I have seen Why does SIGHUP not work on busybox sh in an Alpine Docker container? and tried the approach of trapping both SIGHUP and SIGPIPE (running trap exit SIGHUP SIGPIPE inside the container), unfortunately nothing happens. I'm suspecting maybe the signals are received by the host shell instead of inside the shell inside the container, but I'm not sure how I can leverage that (if that's really what happens) considering I have no way to get the dynamically generated container name, and I can't name the container because I want every single ssh attempt to spawn a different container.

Maybe setting up a connection timout with ClientAliveInterval and ClientAliveCountMax from /etc/ssh/sshd_config will help. By default it is not active.

https://linux.die.net/man/5/sshd_config

I think this answer may help you: https://unix.stackexchange.com/a/85429
For example you can try something like this:

#!/bin/bash
[[ "$PAM_USER" -ne "test" ]] && exit 0

SESSION_COUNT="$(w -h "$PAM_USER" | wc -l)"

if (( SESSION_COUNT == 0 )) && [[ "$PAM_TYPE" == "close_session" ]]; then
  docker kill <containerId>
fi

You should use some unique tag for containerId maybe you can associate id of the container with the session id

You could add this in your /bin/test-shell script:

#!/bin/bash
# Generate a random name for container
CONTAINER_NAME=${RANDOM}

# Register script to stop container with name
trap '/bin/stop-container "$CONTAINER_NAME"' EXIT

# Run container with name
docker run --name $CONTAINER_NAME -it --rm --network none python:3.10-alpine /bin/sh

# Unregister trap if normal exit
trap - EXIT

At the moment, I can't test it, but it could works, because as described in trap manual:

The environment in which the shell executes a trap on EXIT shall be identical to the environment immediately after the last command executed before the trap on EXIT was taken.

Hope this help you to find the right direction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM