Reputation: 815
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".
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
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
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:
~/.ssh/environment
: variables injected by ssh
, see PermitUserEnvironment
/etc/environment
: used by pam_env
on login/etc/profile
, ~/.bashrc
and alike: configs used by the (login) shell, see bash
for example.Also depending on your use case you have now various options how to add these files to the container:
ADD
the respective file to the image or create it in the Dockerfile
ARG
s (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)ENTRYPOINT
script to generate the respective file on startup from the passed environment variables or command line argumentsdocker secret
for sensitive data here)Upvotes: 6
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