Search code examples
bashdockerherokuopenssh

Heroku: "heroku ps:exec" not working when deploying a container into a dyno


I'm deploying a Tensorflow Serving container to Heroku, everything is working fine, but when I try to ssh into the container for executing some commands, Heroku returns this error:

C:\Users\whitm\Desktop\CodeProjects\deep-deblurring-serving>heroku ps:exec
Establishing credentials... error
 !    Could not connect to dyno!
 !    Check if the dyno is running with `heroku ps'

The Dyno is running correctly:

C:\Users\whitm\Desktop\CodeProjects\deep-deblurring-serving>heroku ps
Free dyno hours quota remaining this month: 550h 0m (100%)
Free dyno usage for this app: 0h 0m (0%)
For more information on dyno sleeping and how to upgrade, see:
https://devcenter.heroku.com/articles/dyno-sleeping

=== web (Free): /bin/sh -c bash\ heroku-exec.sh (1)
web.1: up 2020/04/11 19:13:51 -0400 (~ 38s ago)

I found a StackOverflow question from two years ago: Shell into a Docker container running on a Heroku dyno. How?. I already take care of all the details explained on the question, and the official Heroku docs about this specific situation: https://devcenter.heroku.com/articles/exec#using-with-docker, but I'm can't make this working.

This is my Dockerfile:

FROM tensorflow/serving
LABEL maintainer="Whitman Bohorquez" description="Build tf serving based image. This repo must be used as build context"

COPY / /

RUN apt-get update \
&& apt-get install -y git \
&& git reset --hard \
&& apt-get install -y curl \
&& apt-get install -y openssh-server

ENV MODEL_NAME=deblurrer

# Updates listening ports
RUN echo '#!/bin/bash \n\n\
tensorflow_model_server \
--rest_api_port=$PORT \
--model_name=${MODEL_NAME} \
--model_base_path=/models/${MODEL_NAME} \
"$@"' > /usr/bin/tf_serving_entrypoint.sh \
&& chmod +x /usr/bin/tf_serving_entrypoint.sh

# Setup symbolic link from sh to bash
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

CMD bash heroku-exec.sh

Special care in the line RUN rm /bin/sh && ln -s /bin/bash /bin/sh. Im installing Curl, OpenSSH, Python already in the container. I create the file heroku-exec.sh with [ -z "$SSH_CLIENT" ] && source <(curl --fail --retry 3 -sSL "$HEROKU_EXEC_URL") inside it, and successfully copy it into the /app/.profile.d folder, that is, the final route of the file is /app/.profile.d/heroku-exec.sh. Inclusive I tried do the last step as if the container is in a Heroku Private Space (that is not the case) but I will remove that.

Don't know what else to try, hope some help, I feel I'm doing something wrong with the heroku-exec.sh file, but what you think?

Thanks in advance!


Solution

  • I faced the same issue and this solution worked for me.

    Note: Make sure you are creating container from an image that has all binaries that Heroku requires.

    FROM --platform=linux/amd64 heroku/heroku:20
    
    1. Add buildpack using this script

    2. Enable the heroku-exec feature on app:

      heroku features:enable runtime-heroku-exec

    3. Add a .profile.d directory in our DockerFile and have it copied over (use COPY command) to /app/.profile.d. Use the heroku-exec.sh from buildpack version and make sure it's present in the .profile.d before copy.

    4. Add execution permission on heroku-exec.sh after copy.

    5. Add this run command to Dockerfile after the copy -

      RUN rm /bin/sh && ln -s /bin/bash /bin/sh

    6. Finally use heroku ps:exec -a <appName> --dyno=<dynoName> to login.