2

I'm aware, that one can run docker commands in a container by passing in the socket as described here as well as multistage builds as detailed here

My usecase is a bit different. I'm trying to build a Docker Container for SCION, which itself uses Docker.

A "quick & dirty" solution could be to simply run ./scion.sh topology on startup of the container, with passed in Docker socket, however that wouldn't be the most efficient way, since the command takes some time to run.

Therefore the question is, can I run Docker commands during the build phase?

wawa
  • 4,816
  • 3
  • 29
  • 52

2 Answers2

2

Yes, you can.

The examples below will print out the running containers on the host during build phase.

If your docker daemon is already accepting tcp connections on 2375 then here is an example of how to do it:

docker build -t docker-test --network host - << EOF
FROM docker:latest
# if 0.0.0.0 doesn't work for you then replace it with host IP
ARG DOCKER_HOST=tcp://0.0.0.0:2375
RUN docker container ls
EOF

If your host is not accepting TCP connections and you don't want to enable that, then you can run a parallel SOCAT container that will forward traffic on 2375 to the docker socket. Here is how you start it:

docker run -d --rm \
 -v /var/run/docker.sock:/var/run/docker.sock \
-p 127.0.0.1:2375:12345 \
bobrik/socat TCP-LISTEN:12345,fork UNIX-CONNECT:/var/run/docker.sock

Check the container starts and then run the docker build command to see it work.

I tested this on MacOS and Linux.

UPDATE:

Based on the comments, here is a more secure solution:

docker run -d --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
--hostname socat \
--name socat \
bobrik/socat TCP-LISTEN:12345,fork UNIX-CONNECT:/var/run/docker.sock

docker build -t docker-test --network container:socat - << EOF
FROM docker:latest
# if 0.0.0.0 doesn't work for you then replace it with host IP
ARG DOCKER_HOST=tcp://socat:12345
RUN docker container ls
EOF

This way your build process connects to a different container and no need to join the host network.

Mihai
  • 9,526
  • 2
  • 18
  • 40
  • that works like a charm! For my usecase I would however need Ubuntu 18.04 as base image (for some of the dependencies), while the docker image is built on alpine. Can I simply use an ubuntu:18.04 base image and install docker in it, would I need to have a multistage build and copy the docker executable from the docker image or how would I need to proceed in that case? – wawa Jun 24 '20 at 09:19
  • 1
    You only need the docker client, nothing else. You can simply install it in Ubuntu or even only download the executable and put it on the path. I used the docker image because I didn't want the example to be too big and miss the point. – Mihai Jun 24 '20 at 09:24
  • Remember that setting this up is a huge security risk – anyone who can run any `docker` command can trivially take over the entire host. I would not recommend enabling network access to the Docker API at all, even limited to the local system. – David Maze Jun 24 '20 at 10:23
  • @DavidMaze is not completely wrong, thanks for challenging me to find a better way. Docker build is a "sensible" process and should be executed in controlled, isolated environment. You should know what you are doing in the Dockerfile and you should trust the base image. As for the `docker` command, I don't give it more power that it already has – Mihai Jun 24 '20 at 11:53
  • Good point @DavidMaze in this case it will only be used for the local dev environment, but it's a good point to note! – wawa Jun 24 '20 at 11:57
0

In some cases, if you run docker in docker, you sometimes have to simply bind the host's /var/run/docker.sock into the running container.

You can simply do that by binding a volume with same path, and the container will be able to find it.

eja
  • 4,677
  • 3
  • 21
  • 30