VerteXVaaR
VerteXVaaR

Reputation: 815

docker-compose env vars not available when connecting via ssh

I have a local dev env which requires different hosts reachable via SSH so i set up a docker-compose.yml with some services:

services:
  ssh1:
    build:
      context: ./.project/docker/ssh1
      dockerfile: Dockerfile
    environment:
      MYSQL_USER: app1
      MYSQL_PASSWORD: app1

The Dockerfile contains following contents:

FROM ubuntu:20.04

RUN export DEBIAN_FRONTEND=noninteractive \
    && ln -fs /usr/share/zoneinfo/Europe/Berlin /etc/localtime \
    && apt update \
    && apt upgrade -y \
    && apt install -y openssh-server rsync php \
    && mkdir /run/sshd/ \
    && ssh-keygen -A \
    && for key in $(ls /etc/ssh/ssh_host_* | grep -v pub); do echo "HostKey $key" >> /etc/ssh/sshd_config; done \
    && addgroup --gid 1000 app \
    && adduser --gecos "" --disabled-password --shell /bin/bash --uid 1000 --gid 1000 app \
    && mkdir -m 700 /home/app/.ssh/ \
    && chown app:app /home/app/.ssh/ \
    && rm -rf /var/lib/apt/lists/*
COPY --chown=app:app ssh1_rsa.pub /home/app/.ssh/authorized_keys
CMD ["/usr/sbin/sshd", "-D"]
EXPOSE 22

I can verify, that the environment variables are set in the container

$ docker-compose exec ssh1 printenv | grep MYSQL
MYSQL_USER=app1
MYSQL_PASSWORD=app1

docker inspect project_ssh1_1 also shows the ENV variables.

But when i connect from another container to ssh1 via ssh, my environment variables are not set.

Why are my environment variables not set when i ssh into the container?

I also appreciate any in-depth input on how env vars are set in the container via docker and how env vars are inherited from processes or the "OS".


Solution edit:

The actual question was answered. However, i did not ask the right question. So here's my actual solution. I am able to set the ENV VARS in the SSH session with the help of a pretty hacky solution, which should not be used in PROD environments, since it could lead to information disclosure.

Add all ENV VARS as build args. docker-compose.yml:

  ssh1:
    build:
      context: ./.project/docker/ssh1
      dockerfile: Dockerfile
      args:
        MYSQL_ROOT_PASSWORD: root
        MYSQL_DATABASE: app1
        MYSQL_USER: app1
        MYSQL_PASSWORD: app1
        MYSQL_HOST: mysql1

And write them to $HOME/.ssh/environment as well as enabling PermitUserEnvironment. Don't do this in production

Dockerfile

FROM ubuntu:20.04

ARG MYSQL_ROOT_PASSWORD
ARG MYSQL_DATABASE
ARG MYSQL_USER
ARG MYSQL_PASSWORD
ARG MYSQL_HOST

RUN echo "MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD" >> /home/app/.ssh/environment \
    && echo "MYSQL_DATABASE=$MYSQL_DATABASE" >> /home/app/.ssh/environment \
    && echo "MYSQL_USER=$MYSQL_USER" >> /home/app/.ssh/environment \
    && echo "MYSQL_PASSWORD=$MYSQL_PASSWORD" >> /home/app/.ssh/environment \
    && echo "MYSQL_HOST=$MYSQL_HOST" >> /home/app/.ssh/environment \
    && sed -i 's/#PermitUserEnvironment no/PermitUserEnvironment yes/g' /etc/ssh/sshd_config

Now, when you login, SSH will read the env vars from the users .ssh/environment (app in this case) and set them in the user's SSH session.

Upvotes: 5

Views: 2240

Answers (3)

Tel
Tel

Reputation: 1

Presuming your SSH connection has root powers inside the docker container, you can pull the values directly out of the startup process for that container ... always PID 1 as far as I know.

eval $(xargs -0 -n1 -a /proc/1/environ | fgrep MYSQL_)

Upvotes: 0

acran
acran

Reputation: 9018

Your issue has actually not much to do with docker but is due to the way sshd works: for every connection sshd will setup a new environment wiping out all variables in its own environment, see the Login Process in man sshd.

(It's easy to see why this makes sense: sshd is started by the root user and so may contain sensitive data in its environment variables that should not be leaked to the users. Other variables wouldn't be reasonable to pass to the user session, e.g. HOME, PATH, SHELL)

Depending on your use case there are various ways to pass environment variables to a new ssh session, depending on whether it being an interactive or non-interactive session, running a (login) shell or not:

Also depending on your use case you have now various options how to add these files to the container:

  • if the variables are static: just ADD the respective file to the image or create it in the Dockerfile
  • if the variables are set on build-time: use ARGs (or ENV) to pass the variables to the build and create the respective file from that in the build (as you did in your solution)
  • if the variables should be set on container run-time:
    • use a custom ENTRYPOINT script to generate the respective file on startup from the passed environment variables or command line arguments
    • volume-mount the respective file into the container (you may also use docker secret for sensitive data here)

Upvotes: 6

Milan Markovic
Milan Markovic

Reputation: 1370

Environment variables are present in RUN commands and in the shell you exec into when issuing docker exec command, but when you ssh into an ssh server running inside container, you actually get a brand new shell which doesn’t have those env variables set.

Upvotes: 2

Related Questions