10

Why?
I'm trying to create a general purpose solution for running docker-compose on Heroku. I want to make a one click deployment solution through the use of Heroku Button deployment. This way, a user does not need any knowledge of git, Heroku cli and docker.

The problem.
Docker and the docker daemon are only available when I set the stack to container. There are buildpacks that give you docker and docker-compose CLI but without the docker daemon you cannot run the docker image. So buildpacks won't work.
With the stack set to container I can use the file heroku.yml (article). In there I define my processes. (It replaces Procfile. If I still add a Procfile to my project it will do nothing.)
I can also define a Dockerfile there to build my docker image.
When I however run the docker image the following error pops up:

2019-02-28T15:32:48.462101+00:00 app[worker.1]: Couldn't connect to Docker daemon at http+docker://localhost - is it running?
2019-02-28T15:32:48.462119+00:00 app[worker.1]: 
2019-02-28T15:32:48.462122+00:00 app[worker.1]: If it's at a non-standard location, specify the URL with the DOCKER_HOST environment variable.

The problem is inside the Docker container the Docker daemon is not running. The solution to this is to mount it:
docker run -v /var/run/docker.sock:/var/run/docker.sock ...
And since you cannot use Procfile I cannot run that command. (See above heroku.yml replaces Procfile.) And if I was using a buildpack I could use Procfile but the docker daemon wouldn't be running.....

I tried defining a VOLUME within the Dockerfile and the problem persists. Furthermore a heroku article says "Volume mounting is not supported. The filesystem of the dyno is ephemeral."

On Heroku it is possible to run a docker image. What I am struggling at is running a docker in docker image.
Running a docker in docker image works fine on my VPS by mounting /var/run/docker.sock but this cannot(?) be done on Heroku.

Last words: I'm trying to make this work so that other people can easily deploy software solution even though they are not comfortable with git, heroku cli and docker.

David Maze
  • 130,717
  • 29
  • 175
  • 215
Tin Nguyen
  • 5,250
  • 1
  • 12
  • 32
  • It's been a year. I'm still looking for a solution to this problem. – Tin Nguyen Mar 16 '20 at 15:07
  • Did you try to connect to your daemon through SSH? For security reasons I assume it is not possible to access the Heroku's docker daemon and that's what you are doing locally when you mount the volume. – Folkvir Nov 12 '20 at 10:44
  • On a VPS I can do it fine. On Heroku I can't. SSHing to a Heroku stack app works but the docker daemon is not running as said in the description. SSHing to a docker container probably works (haven't tried) but I don't see how you can access the host from the container. Furthermore when running a stack app it is severely limited (root not available and a lot of other limitations). I'm looking for a Docker container that is running its own Docker daemon. There were work towards it in the past but it seems it has been halted in favor of binding to the host's docker daemon. – Tin Nguyen Nov 12 '20 at 11:07
  • It is not from what I can see: https://hub.docker.com/_/docker. I mean, when your are inside of your deployed container on heroku, are you sure the daemon is not running? The error tells me that you cannot connect to the daemon using this address: `http+docker://localhost`. So again, can you use the tcp://0.0.0.0:2375 or on port 2376 or a custom address if enabled? Use this a reference: https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-socket-option – Folkvir Nov 12 '20 at 11:35
  • I have tried that as well and it didn't work with same error message. I specified the location with the env var `DOCKER_HOST` and tried different URLs including your mentioned one. I also tried `/var/run/docker.sock`. I would really appreciate it if you can create a minimal hello world example with DinD on Heroku. – Tin Nguyen Nov 12 '20 at 12:02
  • Well, after some research on it I think what you try to achieve is not possible, at least on Heroku. They do not allow you to run `--priviledged` container. And DinD works like a charm when working locally but when pushed to Heroku, the `dockerd` answers that you need a root (or priviledged) user to start the daemon. So you might want to use a rootless docker image such docker:stable-dind-rootless (https://hub.docker.com/_/docker). I played with it and didnt found something working and cant spend more time on it. I hope you'll find something :) – Folkvir Nov 13 '20 at 00:05

3 Answers3

2

Unfortunately the answer to your question is: not yet.

For securiy reasons Heroku does not provide to the users the ability to run priviledged containers because the container could access to host capabilities. The documentation is pretty clear about your limitations, e.g: No --priviledged container and no root user either, no VOLUMES and disk is ephemeral.

After playing with DinD images for your concern, I came to the conclusion that trying to run Docker inside a Heroku container is not the right choice and design. I am pretty sure what you are trying to achieve is close to what Heroku is offering to the users. Offering a platform or an application where non-developper can push and deploy applications with just a button can be very interesting in various ways. And it can be done with an application using their Platform API. In this situation a Web application (running on Heroku) may not (up to my knowledge) be able to do what you want. Instead you need to embed in a Desktop application: git, docker, and your app for parsing, verifying, building and pushing your applications/components to Heroku's container registry.

In the end, if you still think what you need a DinD solution, well, your primary solution to use a VPS is the only solution for the moment. But be aware that it may open security vulnerabilities to your system and you may arrive to offer something similar to Heroku's offer when trying to limit those security doors.

Folkvir
  • 280
  • 2
  • 12
  • I'm marking this as the accepted answer since as of now I still don't see how it could be possible. If it becomes possible and someone can supply a new answer with minimum hello world reproduction answer via Heroku Deploy button I'll grant 500 reputation score. – Tin Nguyen Sep 21 '21 at 12:29
0

I don't think you can run a service on Heroku that can use the docker command to start some docker container.

I want to make a one click deployment solution through the use of Heroku Button deployment.

I think you can update the reference of the Deploy button to some of your automation servers (ex: an instance Jenkins already deploy on Heroku/another cloud) to trigger the deploy pipeline and don't let people interact with git/docker, etc.
But yes, you have to deal with a lot of problems like security, parameter. when not using popular solutions like Jenkins/CircleCI login and then deploy...

Đinh Anh Huy
  • 505
  • 4
  • 17
  • You can deploy docker containers on Heroku see https://blog.heroku.com/build-docker-images-heroku-yml and https://devcenter.heroku.com/articles/build-docker-images-heroku-yml But instead of deploying multiple docker containers I want to bundle them in a single container as in the spirit of DinD, Docker in Docker. It would be for the best if there was a Docker container that was running its own Docker daemon. – Tin Nguyen Nov 12 '20 at 09:03
-2

What I did was install it in my dockerfile like this:

RUN curl -fsSLO https://get.docker.com/builds/Linux/x86_64/docker-17.04.0-ce.tgz \
  && tar xzvf docker-17.04.0-ce.tgz \
  && mv docker/docker /usr/local/bin \
  && rm -r docker docker-17.04.0-ce.tgz

Then in the args section for running the docker I added this:

args '--user root -v /var/run/docker.sock:/var/run/docker.sock'

For further explanation on why this works see: stackoverflow.com/q/27879713/354577 This works well for me though.

Travis Tubbs
  • 827
  • 1
  • 14
  • 32