Running OpenSSH in an Alpine Docker Container

37,530

Solution 1

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/

Solution 2

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 alpine
RUN apk update && \
apk add --no-cache sudo bash openrc openssh
RUN mkdir -p /run/openrc && \
    touch /run/openrc/softlevel && \
    rc-update add sshd default
RUN adduser --disabled-password regusr && \
    sh -c 'echo "regusr:<encoded_passwd>"' | chpasswd -e > /dev/null 2>&1 && \
    sh -c 'echo "regusr ALL=NOPASSWD: ALL"' >> /etc/sudoers
VOLUME ["/home/reguser/solution/entrypoint-init.d","/sys/fs/cgroup"]
USER reguser
WORKDIR /home/reguser
RUN mkdir -p $HOME/solution && sudo chown reguser:reguser $HOME/solution
ADD ./entrypoint.sh /home/reguser/solution/
EXPOSE 22
ENTRYPOINT ["./solution/entrypoint.sh"]
CMD ["/bin/bash"]

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

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

exec "$@"

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

#!/bin/bash
sudo sed --in-place --expression='/^#[[:space:]]*Port[[:space:]]\+22$/ s/^#//i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^#[[:space:]]*AddressFamily[[:space:]]\+any$/ s/^#//i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^#[[:space:]]*HostKey[[:space:]]\+\/etc\/ssh\/ssh_host_rsa_key$/ s/^#//i' -- /etc/ssh/sshd_config

sudo sed --in-place --expression='/^#[[:space:]]*HostbasedAuthentication[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*HostbasedAuthentication[[:space:]].*/ s/^[[:space:]]*\(HostbasedAuthentication\)[[:space:]]\(.*\)/\1 no/i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*HostbasedAuthentication[[:space:]]\+yes.*/ s/^/#/i' -- /etc/ssh/sshd_config

sudo sed --in-place --expression='/^#[[:space:]]*IgnoreRhosts[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*IgnoreRhosts[[:space:]].*/ s/^[[:space:]]*\(IgnoreRhosts\)[[:space:]]\(.*\)/\1 yes/i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*IgnoreRhosts[[:space:]]\+no.*/ s/^/#/i' -- /etc/ssh/sshd_config

sudo sed --in-place --expression='/^#[[:space:]]*PasswordAuthentication[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*PasswordAuthentication[[:space:]].*/ s/^[[:space:]]*\(PasswordAuthentication\)[[:space:]]\(.*\)/\1 yes/i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*PasswordAuthentication[[:space:]]\+no.*/ s/^/#/i' -- /etc/ssh/sshd_config

sudo sed --in-place --expression='/^#[[:space:]]*PubkeyAuthentication[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*PubkeyAuthentication[[:space:]].*/ s/^[[:space:]]*\(PubkeyAuthentication\)[[:space:]]\(.*\)/\1 yes/i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*PubkeyAuthentication[[:space:]]\+no.*/ s/^/#/i' -- /etc/ssh/sshd_config

sudo sed --in-place --expression='/^#[[:space:]]*PrintMotd[[:space:]].*/ s/^#//i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*PrintMotd[[:space:]].*/ s/^[[:space:]]*\(PrintMOTD\)[[:space:]]\(.*\)/\1 no/i' -- /etc/ssh/sshd_config
sudo sed --in-place --expression='/^[[:space:]]*PrintMotd[[:space:]]\+yes.*/ s/^/#/i' -- /etc/ssh/sshd_config

sudo sed --in-place --expression='$ a\' --expression='\nAcceptEnv LANG LC_\*' -- /etc/ssh/sshd_config

sudo /etc/init.d/sshd --dry-run start
sudo /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/null
docker 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.

Solution 3

/etc/init.d/sshd: not found

Try to run these commands:

apk add --no-cache openrc
rc-update add sshd
Share:
37,530
Ole
Author by

Ole

Updated on December 31, 2021

Comments

  • Ole
    Ole over 2 years

    I've installed OpenSSH and now I wish to run it as described in the documentation by running /etc/init.d/sshd start. However it does not start:

     / # /etc/init.d/sshd start
     /bin/ash: /etc/init.d/sshd: not found
    

    Thoughts?

    P.S.

    / # ls -la /etc/init.d/sshd 
    -rwxr-xr-x    1 root     root          2622 Jan 14 20:48 /etc/init.d/sshd
    

    Contents of /etc/init.d/sshd:

        #!/sbin/openrc-run
        # Copyright 1999-2015 Gentoo Foundation
        # Distributed under the terms of the GNU General Public License v2
        # $Header: /var/cvsroot/gentoo-x86/net-misc/openssh/files/sshd.rc6.4,v 1.5 2015/05/04 02:56:25 vapier Exp $
    
        description="OpenBSD Secure Shell server"
        description_checkconfig="Verify configuration file"
        description_reload="Reload configuration"
    
        extra_commands="checkconfig"
        extra_started_commands="reload"
    
        : ${SSHD_CONFDIR:=/etc/ssh}
        : ${SSHD_CONFIG:=${SSHD_CONFDIR}/sshd_config}
        : ${SSHD_PIDFILE:=/var/run/${SVCNAME}.pid}
        : ${SSHD_BINARY:=/usr/sbin/sshd}
    
        depend() {
            use logger dns
            if [ "${rc_need+set}" = "set" ] ; then
                : # Do nothing, the user has explicitly set rc_need
            else
                local x warn_addr
                for x in $(awk '/^ListenAddress/{ print $2 }' "$SSHD_CONFIG" 2>/dev/null) ; do
                    case "${x}" in
                        0.0.0.0|0.0.0.0:*) ;;
                        ::|\[::\]*) ;;
                        *) warn_addr="${warn_addr} ${x}" ;;
                    esac
                done
                if [ -n "${warn_addr}" ] ; then
                    need net
                    ewarn "You are binding an interface in ListenAddress statement in your sshd_config!"
                    ewarn "You must add rc_need=\"net.FOO\" to your /etc/conf.d/sshd"
                    ewarn "where FOO is the interface(s) providing the following address(es):"
                    ewarn "${warn_addr}"
                fi
            fi
        }
    
        checkconfig() {
            if [ ! -d /var/empty ] ; then
                mkdir -p /var/empty || return 1
            fi
    
            if [ ! -e "${SSHD_CONFIG}" ] ; then
                eerror "You need an ${SSHD_CONFIG} file to run sshd"
                eerror "There is a sample file in /usr/share/doc/openssh"
                return 1
            fi
    
            if ! yesno "${SSHD_DISABLE_KEYGEN}"; then
                ssh-keygen -A || return 1
            fi
    
            [ "${SSHD_PIDFILE}" != "/var/run/sshd.pid" ] \
                && SSHD_OPTS="${SSHD_OPTS} -o PidFile=${SSHD_PIDFILE}"
            [ "${SSHD_CONFIG}" != "/etc/ssh/sshd_config" ] \
                && SSHD_OPTS="${SSHD_OPTS} -f ${SSHD_CONFIG}"
    
            "${SSHD_BINARY}" -t ${SSHD_OPTS} || return 1
        }
    
        start() {
            checkconfig || return 1
    
            ebegin "Starting ${SVCNAME}"
            start-stop-daemon --start --exec "${SSHD_BINARY}" \
                --pidfile "${SSHD_PIDFILE}" \
                -- ${SSHD_OPTS}
            eend $?
        }
    
        stop() {
            if [ "${RC_CMD}" = "restart" ] ; then
                checkconfig || return 1
            fi
    
            ebegin "Stopping ${SVCNAME}"
            start-stop-daemon --stop --exec "${SSHD_BINARY}" \
                --pidfile "${SSHD_PIDFILE}" --quiet
            eend $?
    
            if [ "$RC_RUNLEVEL" = "shutdown" ]; then
                _sshd_pids=$(pgrep "${SSHD_BINARY##*/}")
                if [ -n "$_sshd_pids" ]; then
                    ebegin "Shutting down ssh connections"
                    kill -TERM $_sshd_pids >/dev/null 2>&1
                    eend 0
                fi
            fi
        }
    
        reload() {
            checkconfig || return 1
            ebegin "Reloading ${SVCNAME}"
            start-stop-daemon --signal HUP \
                --exec "${SSHD_BINARY}" --pidfile "${SSHD_PIDFILE}"
            eend $?
        }
    
  • Ole
    Ole about 8 years
    It is present is usr/sbin. Also running rc-update results in /bin/ash: rc-update: not found
  • Ole
    Ole about 8 years
    when running that I get the same result >>> / # /usr/bin/sshd start /bin/ash: /usr/bin/sshd: not found
  • VonC
    VonC about 8 years
    I see the size of sshd is relatively small. Is it a script? Can you open it and see if it refers in it to non-existent paths?
  • Ole
    Ole about 8 years
    I pasted the contents of /etc/init.d/sshd in the question. The contents of /bin/sbin/sshd` are binary.
  • VonC
    VonC about 8 years
    @Ole does /sbin/openrc-run exists?
  • Ole
    Ole about 8 years
    No - BTW - @VonC you could just start a container and have a look like this: docker run -it --rm alpine /bin/ash
  • timetofly
    timetofly over 7 years
    It's my understanding that example script ONLY can run sshd, and not any other command. How would you make it turn sshd + another application, whatever you specify as the command?
  • FreeSoftwareServers
    FreeSoftwareServers about 4 years
    Link Only Answer :(
  • CSJ
    CSJ about 4 years
    @FreeSoftwareServers maybe click link is too hard for you :)
  • FreeSoftwareServers
    FreeSoftwareServers about 4 years
    @CSJ I would think you would know better as a higher rep user but it's bad to avoid Link_Rot among other things --> en.wikipedia.org/wiki/Link_rot