How to test built image before pushing it to registry?

I want to build pipeline like below

  • build binary
  • do unit test
  • build image
  • run some related service
  • run the image built
  • do integration test
  • push to registry
  • push to staging cluster

seem docker plugin always push image to registry

So someone may have a better way to do this, but here’s a possible solution

Create a second “integration testing repo” that is kicked off as a downstream build of the service that got published. Once it’s published it can be used by the normal “service” section and run the integration test’s you’d want to have in place.

We tend to do rolling and blue/green deployments so testing for us looks different.

Please note that you are not required to use the Docker plugin. The docker plugin is just one of many options that you can use to build and publish images. Below are two alternate approaches you may consider …

You can build, test and publish images with drone the same way you build, test and publish images from your command line terminal:

pipeline:
  build:
    image: docker
    commands:
      - docker build --rm -t octocat/hello-world .
      - docker run --rm octocat/hello-world --test
      - docker login -u <username> -p <password>
      - docker push octocat/hello-world
      - docker rmi octocat/hello-world
    volumes:
+     - /var/run/docker.sock:/var/run/docker.sock

The above example we mount the host machine docker socket. If you do not want to mount the host machine docker socket, one alternative is to start a docker daemon as a service container, which is then available to your build step at runtime:

pipeline:
  build:
    image: docker
    environment:
+     - DOCKER_HOST=unix:///drone/docker.sock
    commands:
+     - sleep 10 # gives docker enough time to initialize
      - docker build --rm -t octocat/hello-world .
      - docker run --rm octocat/hello-world --test
      - docker login -u <username> -p <password>
      - docker push octocat/hello-world
      - docker rmi octocat/hello-world

+services:
+ docker:
+   image: docker:dind
+   privileged: true
+   command: [ '-H', 'unix:///drone/docker.sock' ]

Note that both configurations above require a repository to be trusted, which can be enabled in the Drone user interface by a Drone system administrator.

So we have exact same problem, in addition to that, we consider our builds to be unsafe. Mounting a docker socket from the host is not an option, neither is allowing devs to start privileged services.

Ideally, we would to have a way to start additional containers for each build or modify .drone.yml to inject a docker daemon as a service.

Also if we were able to inject additional ENV variable to each pipeline step per build, we could manage starting docker daemons outside of drone.

It could work like this, by adding DOCKER_HOST=tcp://short-lived-docker-daemon.local:2375:
drone-agent ---> modify-yaml-to-inject-env-data-service ---> drone-agent

If we control how docker daemon is started, we can ensure it is secure, for instance, containers that devs run inside a pipeline, aren’t run as root (--userns-remap), etc.