Running OpenSSH in an Alpine Docker Container Running OpenSSH in an Alpine Docker Container linux linux

Running OpenSSH in an Alpine Docker Container


A container is not a full installed environment.The official document is for that installed alpine on some machine.With power on, boot up services, etc. that a container does not have.

So, anything in /etc/init.d/ can not be used directly in a container which is used by boot up service (like systemd, or alpine's rc*). That's why you got error messages cause the rc* isn't installed in the container.

What you need to do is start sshd manuanlly.You can take look on below example:

https://hub.docker.com/r/danielguerra/alpine-sshd/~/dockerfile/


/etc/init.d/sshd: not found

Try to run these commands:

apk add --no-cache openrcrc-update add sshd


Despite there are some details still not clear to me, let me take a voice in the discussion. The solution specified by the below configuration works for me. It's the result of arduous experiments.

First, the dockerfile

FROM alpineRUN apk update && \apk add --no-cache sudo bash openrc opensshRUN mkdir -p /run/openrc && \    touch /run/openrc/softlevel && \    rc-update add sshd defaultRUN adduser --disabled-password regusr && \    sh -c 'echo "regusr:<encoded_passwd>"' | chpasswd -e > /dev/null 2>&1 && \    sh -c 'echo "regusr ALL=NOPASSWD: ALL"' >> /etc/sudoersVOLUME ["/home/reguser/solution/entrypoint-init.d","/sys/fs/cgroup"]USER reguserWORKDIR /home/reguserRUN mkdir -p $HOME/solution && sudo chown reguser:reguser $HOME/solutionADD ./entrypoint.sh /home/reguser/solution/EXPOSE 22ENTRYPOINT ["./solution/entrypoint.sh"]CMD ["/bin/bash"]

Next, /home/reguser/solution/entrypoint.sh

#!/bin/bashfor f in ./solution/entrypoint-init.d/*; do    case "$f" in       *.sh)     echo "$0: running $f"; . "$f" ;;       *)        echo "$0: ignoring $f" ;;    esac    echodoneexec "$@"

Next, /home/reguser/solution/entrypoint-init.d/10-ssh-up.sh

#!/bin/bashsudo sed --in-place --expression='/^#[[:space:]]*Port[[:space:]]\+22$/ s/^#//i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^#[[:space:]]*AddressFamily[[:space:]]\+any$/ s/^#//i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^#[[:space:]]*HostKey[[:space:]]\+\/etc\/ssh\/ssh_host_rsa_key$/ s/^#//i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^#[[:space:]]*HostbasedAuthentication[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*HostbasedAuthentication[[:space:]].*/ s/^[[:space:]]*\(HostbasedAuthentication\)[[:space:]]\(.*\)/\1 no/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*HostbasedAuthentication[[:space:]]\+yes.*/ s/^/#/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^#[[:space:]]*IgnoreRhosts[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*IgnoreRhosts[[:space:]].*/ s/^[[:space:]]*\(IgnoreRhosts\)[[:space:]]\(.*\)/\1 yes/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*IgnoreRhosts[[:space:]]\+no.*/ s/^/#/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^#[[:space:]]*PasswordAuthentication[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*PasswordAuthentication[[:space:]].*/ s/^[[:space:]]*\(PasswordAuthentication\)[[:space:]]\(.*\)/\1 yes/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*PasswordAuthentication[[:space:]]\+no.*/ s/^/#/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^#[[:space:]]*PubkeyAuthentication[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*PubkeyAuthentication[[:space:]].*/ s/^[[:space:]]*\(PubkeyAuthentication\)[[:space:]]\(.*\)/\1 yes/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*PubkeyAuthentication[[:space:]]\+no.*/ s/^/#/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^#[[:space:]]*PrintMotd[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*PrintMotd[[:space:]].*/ s/^[[:space:]]*\(PrintMOTD\)[[:space:]]\(.*\)/\1 no/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='/^[[:space:]]*PrintMotd[[:space:]]\+yes.*/ s/^/#/i' -- /etc/ssh/sshd_configsudo sed --in-place --expression='$ a\' --expression='\nAcceptEnv LANG LC_\*' -- /etc/ssh/sshd_configsudo /etc/init.d/sshd --dry-run startsudo /etc/init.d/sshd start

The last two lines are in the heart of the trick. In particular, the sudo /etc/init.d/sshd --dry-run start makes the solution working.

Finally, command-line controls

docker build --tag='dockerRegUser/sshdImg:0.0.1' --file='./dockerfile' .docker container create --tty \       --volume $(pwd)/dock/entrypoint-init.d:/home/reguser/solution/entrypoint-init.d:ro \       --name sshdCnt 'dockerRegUser/sshdImg:0.0.1' tail -f /dev/nulldocker start sshdCnt && \ssh-keygen -f "/home/user/.ssh/known_hosts" -R "$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' sshdCnt)" && \sleep 5 && \ssh-copy-id -i ~/.ssh/sshkey reguser@$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' sshdCnt)

I know, I know, there is a lot of unnecessary constructs. The example is also against the single service docker container principle. But there are phases and situations in solution development and delivery lifecycle that justify (or at least tempt) considering extending the container with the sshd or other openrc-controlled services.