Docker as a Shell Wrapper

This is a recipe for creating a simple docker image, as a wrapper for your shell. Any command you would normally execute on the command line, can be routed to a docker image instead, and executed inside the container.

Your home directory and current directory is mounted into the container, causing your command to be executed transparently.

Base Image

# syntax=docker/dockerfile:1.3

FROM ubuntu:20.04

RUN apt update && \
    DEBIAN_FRONTEND=noninteractive \
    apt install -y --no-install-recommends \
    openssh-client \
    python3 \
    git \
    && rm -rf /var/lib/apt/lists/*

ADD entrypoint.sh /entrypoint.sh

ENTRYPOINT [ "/entrypoint.sh" ]

entrypoint.sh

The entrypoint script creates a user which mimics the user invoking the docker run command. This allows the docker container to access the mounted home directory.

#!/bin/bash

# Create a user mimicing the user outside the docker image.
# This enables a user to access their own home, mounted inside the image.
# All variables mentioned must be injected at run-time (docker run -e ...)
groupadd -g $GID $NAME
useradd -u $ID -g $GID -p "" $NAME
usermod -aG root $NAME

# Spawn a subshell as the newly created user. Pass all commandline arguments
# on to the subshell.
# session command allows a user to invoke /bin/bash directly, to get an
# interactive shell.
su --shell /bin/bash --login $NAME --session-command "cd $PWD; eval '$*'"

Run the Image as an Interactive Shell

Setting /bin/bash as the command, drops us directly into an interactive shell inside the container. Because the home directory has been mounted, and a mirror user has been set up, your own .bashrc will be loaded.

ID=$(id -u)
GID=$(id -g)
NAME=$(whoami)

docker run \
    -it \
    --rm \
    -e ID=$ID \
    -e GID=$GID \
    -e NAME=$NAME \
    -v $HOME:$HOME \
    -w $(pwd) \
    --net host \
    shell_wrapper /bin/bash

some-user:~/shell_wrapper$ ls
Dockerfile  README.md  entrypoint.sh  makefile
some-user:~/shell_wrapper$ whoami
some-user

One-off Commands

ID=$(id -u)
GID=$(id -g)
NAME=$(whoami)

docker run \
    --rm \
    -e ID=$ID \
    -e GID=$GID \
    -e NAME=$NAME \
    -v $HOME:$HOME \
    -w $(pwd) \
    --net host \
    shell_wrapper ls -la

total 28
drwxrwxr-x 2 some-user some-user 4096 Oct 15 21:23 .
drwxrwxr-x 5 some-user some-user 4096 Oct 15 20:19 ..
-rw-rw-r-- 1 some-user some-user  299 Oct 15 21:23 Dockerfile
-rw-rw-r-- 1 some-user some-user  285 Oct 15 20:20 README.md
-rwxrwxr-x 1 some-user some-user  825 Oct 15 21:31 entrypoint.sh
-rw-rw-r-- 1 some-user some-user   74 Oct 15 20:36 makefile