How to open an SSH tunnel during the build process of PostGIS container build?
I need to SSH tunnel to database, so I can create dump, then restore in container.
With other docker containers, I usually create a startup.sh
then run from Dockerfile
. However, to run startup scripts in PostGIS container we need to add the script to /docker-entrypoint-initdb.d
folder.
The problem with this is, the script runs as user postgres with a user id of 999. I need to run as root with userid of 0 to execute ssh commands.
Instructions run from the Dockerfile
execute under the root user, but again once the scripts are run from /docker-entrypoint-initdb.d
, they are run under the postgres user.
If I run docker exec -it postgis_container bash
, I am in bash as the root user and I can execute all the commands I need. However, I do not want to do this. I want to just execute docker-compose up
and allow the docker compose configurations, the Dockerfile
and possible any startup script to do the rest.
I know I can install OpenSSH and run tunnel from Dockerfile
but connecting to a server the first time brings up the known_host
prompt. I can user ssh-keyscan -H some_server >> /root/.ssh/known_hosts
or even make a volume from the host machine of my ~/.ssh
folder, that containers working a known_host
file but the error I get is:
Dockerfile
RUN echo "Install OpenSSH \n" \
&& apt-get -y update \
&& apt-get install -y openssh-client \
&& echo "Config SSH \n" \
&& mkdir /root/.ssh && touch /root/.ssh/id_rsa-dev \
&& chmod 700 /root/.ssh/id_rsa-dev \
&& touch /root/.ssh/known_hosts \
&& touch /root/.ssh/config \
&& ssh-keyscan -H some_server.com >> /root/.ssh/known_hosts \
&& echo "Tunnel to DB \n" \
&& ssh -N -L 9001:some_other_server.com:5432 some_user@some_server.com -i /root/.ssh/id_rsa-dev & \
&& echo "Setup for dump and restore \n" \
&& cd /root/dump \
&& date_today=$(date +%F) \
&& echo "Createing dump file from dev db name = dev_db_$date_today.sql" \
&& export PGPASSWORD=${DEV_DB_PASSWORD} \
&& pg_dump -Fc -v -U dbuser -d dev_db -p 9001 -h 0.0.0.0 > ./dev_db_$date_today.sql \
&& export PGPASSWORD=$POSTGRES_PASSWORD \
&& echo "Restoring db" \
&& pg_restore -Fc -v -U dbuser -d dev_db_docker_local ./dev_db_$date_today.sql
Error from output
0.335 Warning: Permanently added the ECDSA host key for IP address ‘111.222.333.444’ to the list of known hosts.
#0 0.418 Authorized uses only. All activity may be monitored and reported.
#0 0.418 Load key "/root/.ssh/id_rsa-dev": invalid format
#0 0.418 some_user@some_server.com: Permission denied (publickey).
However, again, if I run docker exec -it postgis_container bash
, then execute the exact same commands, I am able to open the ssh tunnel, dump and restore.
startup.sh
#!/usr/bin/env bash
cho "Install OpenSSH
apt-get -y update
apt-get install -y openssh-client
echo "Config SSH
mkdir /root/.ssh && touch /root/.ssh/id_rsa-dev
chmod 700 /root/.ssh/id_rsa-dev
touch /root/.ssh/known_hosts
touch /root/.ssh/config
ssh-keyscan -H some_server.com >> /root/.ssh/known_hosts
echo "Tunnel to DB
ssh -N -L 9001:some_other_server.com:5432 some_user@some_server.com -i /root/.ssh/id_rsa-dev &
echo "Setup for dump and restore
cd /root/dump
date_today=$(date +%F)
echo "Createing dump file from dev db name = dev_db_$date_today.sql"
export PGPASSWORD=${DEV_DB_PASSWORD}
pg_dump -Fc -v -U dbuser -d dev_db -p 9001 -h 0.0.0.0 > ./dev_db_$date_today.sql
export PGPASSWORD=$POSTGRES_PASSWORD
echo "Restoring db"
pg_restore -Fc -v -U dbuser -d dev_db_docker_local ./dev_db_$date_today.sql
I would prefer to be able to run my startup.sh
script from /docker-entrypoint-initdb.d
folder as a root user. But If I can not, then would like to be able to added all the steps to Dockerfile
Any help would be greatly appreciated.
Note:
I asked a question here.
I was trying to find out how to get my startup script to run as root, but realized the question did not give enough context so I created this post. I mention this because setting user root or 0, wether in the Dockerfile
or the docker-compose.yml
does not solve my problem.
If I try to run startup.sh from /docker-entrypoint-initdbd
:
sudo
is not available. su
is available, but I do not know root password. gosu
is available but when I used that it give an error along the lines of operation not permitted.
Update 1:
Seems like this is an issue. The postgres docker github says you can not run as root from /docker-entrypoint-initdb.d
.
https://github.com/docker-library/postgres/issues/973
But something seems weird about that. I figure there has got to be a way around this. Or maybe some best practice that address this use case. I imagine I am not the only one who has run into an issue like this.
Update 2:
I just realized running the commands in Dockerfile
will not work because postgres would not have been started yet. And I need to run psql after I open the tunnel. So I have to run from /docker-entrypoint-initdb.d
folder or figure out some way to get startup.sh
to run after postgis container finishes its default start up processes.
Appearently this was not a problem a few years ago, but I believe there was a move to stop the use of root access during the build start up process in the /docker-entrypoint-initdb.d
for security reasons. But there was no suggested work around.