0

We've begun to use containers when creating tools and utilities so individual developers don't have to bother installing prerequisites. Works great, as in:

docker run --rm -v $PWD/input.yaml:/input.yaml  our.registry.com/dev/toolA /input.yaml

Until toolA needs to call another utility, toolB, that is also wrapped in a container.

Is there a generic way to run a container from within a container, so that it works with docker, podman, or whatever the container-tech-du-jour is without toolA's caller having to add "scary" extra parameters like e.g. --privileged=true or -v /var/run/docker.sock:/var/run/docker.sock?

I'm aware that one can run docker-in-docker, and apparently one can also run podman-in-podman, but that is not recommended. Adding -v /var/run/docker.sock:/var/run/docker.sock is the recommended approach, but that is docker-only, right?

Because otherwise this is a leaky abstraction. Currently I build toolA by including the essential bits of the toolB container in toolA, making toolA sensitive to changes in the implementation of toolB, which I'd like to avoid. Or I could build toolA but only support docker and require users to add the -v /var/run/docker.sock:/var/run/docker.sock parameter :-(.

Is there a more elegant way to call toolBs container from inside toolA's container that works with all common container techs and doesn't require extra parameters when starting toolA?

atline
  • 28,355
  • 16
  • 77
  • 113
Peter V. Mørch
  • 13,830
  • 8
  • 69
  • 103

3 Answers3

1

Is there a generic way to run a container from within a container [...] without having to add "scary" extra parameters like [...] -v /var/run/docker.sock:/var/run/docker.sock?

No.

(You do have to mount the host's Docker socket; the calling container does not need to be --privileged; you cannot limit what the calling container can do once it has access to the socket, so it can itself launch privileged containers, or launch a container bind-mounting the host's /etc directory, or otherwise do naughty things. I'm not actually sure how this interacts with Podman.)

Especially if the container needs to write back to the host system, it's hard to make the docker run command be usably compact. You'll need a -u option to specify the host user ID, -v options for the Docker socket and the current directory, --rm, and the repository name, all as overhead, every time you run the command. I might prefer using a native command, maybe in a widely-available scripting language like Python or the Bourne shell.

If you still want to run this from a container, you could COPY or otherwise install tool B into the same container, so you can make a normal subprocess invocation to launch it; or break tool B into a library and an application, and include the library in tool A (kind of what you're doing now but more formalized).

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • 1
    Ok, well now I know for sure. I was expecting that I could run a (sub-)container exposing only exactly what the container has access to, and nothing else. It seems I can't. What I'm doing currently is exactly what you're suggesting COPY-ing the relevant bits from toolB into the image I'm building for toolA. But it sorta sucks when I have toolB as docker container created by someone else. – Peter V. Mørch Mar 04 '21 at 14:13
  • What is your problem with the container? Do you have the Dockerfile of the toolB container? – jordanvrtanoski Mar 04 '21 at 14:17
  • My problem is one of encapsulation. The team behind toolB expose the interface of a docker container. By messing with the internals of the toolB container, A) I'm not using the published interface and B) calling toolB just becomes much more cumbersome. It is a little like calling private interfaces or methods using reflection or some such hacky approach. Sure, it already works by extracting toolB from its container, but it is a _hack_. – Peter V. Mørch Mar 04 '21 at 14:22
0

The approach to run a container from inside container is unorthodox and it can be avoided by redesigning the flow. It will work, but it will create huge complexity and overhead.

If you need the tool just for the period during the build, you can use multi-stage builds. What you need to do is to create a base container usually called builder that has all the tools that are needed for the build, fetch the project in the base container and run the build. After the build is finished, you will move to the next stage and create a base runner where you will install only the required libraries and modules for the runtime environment and add the resulting files from the builder to the runner container.

In this way, you will have full control over both build-time and run-time environments. In addition, if you have multiple projects, or complex builds, you can use the multi-stage build in combination with buildx to run the build in parallel.

jordanvrtanoski
  • 5,104
  • 1
  • 20
  • 29
  • 1
    Unfortunately, toolB is needed at run-time, not build-time. And toolB is created by somebody else. What I'm doing is using a multi-stage build, and COPY-ing toolB from the container for toolB. – Peter V. Mørch Mar 04 '21 at 14:15
0

Passing in -v /var/run/docker.sock:/var/run/docker.sock to the outer container is problematic from a security point of view as it gives the outer container permission to run containers on the host. A malicious outer container could run such containers with bind-mounts so that host directories could be written to.

Running the outer container with Podman as your normal user (rootless) with --privileged is protecting you from that scenario. The outer container will only be able to write to the directories that you pass in as bind-mounts (e.g. with the -v command-line option).

The meaning of the --privileged flag is explained in this Red Hat article.

Update June 2021. It's not necessary anymore to pass the --privileged flag when running Podman in Podman. See my example in https://stackoverflow.com/a/64537135/757777 and the Red Hat blog post How to use Podman inside of a container

Erik Sjölund
  • 10,690
  • 7
  • 46
  • 74
  • Yeah, so running docker in docker is not recommended, `-v /var/run/docker.sock:/var/run/docker.sock` to the outer container is sort-of more recommended but problematic from a security point of view, and podman with `--privilege` is sorta better except nobody is actually using podman (docker/podman usage ratio is 72:1 according to [google trends](https://trends.google.com/trends/explore?q=%2Fm%2F0wkcjgj,podman)). :-( This is still immature tech... – Peter V. Mørch Mar 05 '21 at 15:49