I was recently asked how one could build and then test a container using a docker-in-docker service container. Below is a contrived example that demonstrates how this is technically possible. The example is completely self contained, which means you can copy this and run with drone exec, if you want.
So what are the pros and cons to this approach? The pro is that your pipeline is isolated from the host machine. The cons are that pipelines are ephemeral which means docker layers are not persisted between builds. Also the dind images runs in privileged mode, which means a bad actor could break out of the container runtime and access your host machine. This should only be used in trusted environments (behind the firewall, private repositories, etc).
kind: pipeline
type: docker
name: default
steps:
# this code will create a dummy Dockerfile. This is just
# here so that our yaml file is self-contained.
- name: setup
image: golang
commands:
- |
cat <<EOF > index.html
hello world
EOF
- |
cat <<EOF > Dockerfile
FROM busybox
ADD index.html /www/index.html
EXPOSE 8000
CMD httpd -p 8000 -h /www; tail -f /dev/null
EOF
- name: build
image: docker:17.05.0-ce-dind
environment:
- DOCKER_HOST=tcp://docker:2375
commands:
- sleep 5
- docker ps
- docker build -t hello-world .
# start the container using a detached (non-blocking)
# step. Bonus we can see our container logs in the
# build output.
- name: run
image: docker:17.05.0-ce-dind
detach: true
environment:
- DOCKER_HOST=tcp://docker:2375
commands:
- docker run -p 8000:8000 hello-world
# this container just runs a docker ps to verify
# our container is running. Just for demo purposes,
# not really needed.
- name: check_running
image: docker:17.05.0-ce-dind
environment:
- DOCKER_HOST=tcp://docker:2375
commands:
- sleep 5
- docker ps
# curl the container to test it is up and running.
# notice that we use `docker:8000` since the container
# is running in the docker service container.
- name: test
image: golang # because I know it has curl installed
commands:
- curl -v http://docker:8000
services:
docker:
image: docker:17.05.0-ce-dind
privileged: true
I recommend opening an issue with the Docker team for this. As I recall, they did not ship arm or arm64 images because the official install script (https://get.docker.com/) did not support those architectures. This has since changed, so perhaps now they would consider shipping an armv7 image.
EDIT: according the the library/docker manifest it looks like they have official linux arm images available for download. If you run docker pull docker:18.02.0-ce-dind on arm it should pull the arm version of the image. They appear to officially support arm v6 and v8.
Ok, pull command worked on armv7 scaleway machine. I will try then you approach for testing docker images as we use amd64 and armv7 agents.
Thanks for helping!
I’ve noticed, however, that detached steps go on forever, and the pipeline never ends. Is this the normal behavior?
My plan is to:
Restore a cache using the Drone S3 cache plugin.
Start Docker DIND, mounting the cache as the DIND storage, so I can preserve cached layers.
Run my tests - using docker-compose within the Drone build.
For that, it looks like I need to start DIND as a step rather than as a service… but whenever the following steps finish, the DIND step keeps running forever!