Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Building Docker Images with Drone.io

I'm running my own Drone instance in AWS and I want it to build a docker image and push it to my repo. Drone runs its build environment in a docker container, so I basically want to build docker images from inside a docker container. I found this and saw you can Bind Mount the docker socket. How do I do this with Drone?

docker run -it -v /var/run/docker.sock:/var/run/docker.sock mycompany/buildimage

So I can run docker build from inside my container. Or do you know of another CI tool that I can run my custom script and build docker images.

like image 845
Bernie Perez Avatar asked Jul 25 '14 01:07

Bernie Perez


3 Answers

Note that this answer applies to drone version 0.5

You can use the Docker plugin to build and publish a Docker image as a step in your build pipeline. In the example .drone.yml file below I've added a publish step that uses the docker plugin. Note that you will need to replace foo/bar with the name of the DockerHub repository you intend to publish to.

pipeline:
  build:
    image: golang
    commands:
      - go build
      - go test
  publish:
    image: plugins/docker
    repo: foo/bar

In many cases you will want to limit execution of the this step to certain branches. This can be done by adding runtime conditions:

  publish:
    image: plugins/docker
    repo: foo/bar
    when:
      branch: master

You will need to provide drone with credentials to your Docker registry in order for drone to publish. These credentials can be declared directly in the yaml file, although storing these values in plain text in the yaml is generally not recommended:

  publish:
    image: plugins/docker
    repo: foo/bar
    username: johnsmith
    password: pa55word
    when:
      branch: master

You can alternatively provide your credentials using the built-in secret store. Secrets can be added to the secret store on a per-repository basis using the Drone command line utility:

  export DRONE_SERVER=http://drone.server.address.com
  export DRONE_TOKEN=...

  drone secret add --image plugins/docker \
    octocat/hello-world DOCKER_USERNAME johnsmith

  drone secret add --image plugins/docker \
    octocat/hello-world DOCKER_PASSWORD pa55word

In the above example the --image flag is used to limit which secrets we expose our Docker credentials to, which we set to the docker plugin. The octocat/hello-world parameter represents your GitHub repository name and should be replaced with the correct value.

Mouting Voumes (alternate approach)

You also asked if it were possible to mount the Docker socket into your build environment. This is possible, but will require some additional permissions (mark your build as trusted in the UI)

pipeline:
  build:
    image: docker
    commands:
      - docker build ...
      - docker run ...
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

The only issue with this approach is if your build fails you may not be able to cleanup images or containers that were created during your build.

In addition you should not use this approach if your repository is public and accepts pull requests. Exposing your host machine Docker socket to your build environment could be exploited by malicious pull requests, allowing access to your host machine.

like image 165
Brad Rydzewski Avatar answered Oct 19 '22 10:10

Brad Rydzewski


I wrote an article with steps to get Drone to output a Docker container, and I also address some of the common problems.

Keep in mind that Drone's build environment is itself a Docker container, which means you'll be in a Docker-in-Docker situation: out of the box, Docker doesn't run correctly inside a Docker container. The accepted solution is to use the wrapdocker script to start the inner Docker instance. My final setup looks like:

Docker in Drone

For Drone, you'd add something like the following to your build environment's Dockerfile:

# install docker
RUN apt-get install -y apparmor  
RUN curl -s https://get.docker.io/ubuntu/ | sudo sh  
ADD wrapdocker /usr/local/bin/wrapdocker
RUN chmod +x /usr/local/bin/wrapdocker

This assumes the wrapdocker script is available locally. Alternately, you could grab wrapdocker from github directly. Then, given a .drone.yml file like:

image: http://my-docker-registry/my-docker-image:version  
script:  
  - ./.drone/build.sh

your build.sh would look like:

#!/bin/bash
set -e  
cd /var/cache/drone/src/path/to/app

# [pass tests here]

wrapdocker &  
sleep 5

docker build -t docker-registry/image-name .  
docker push docker-registry/image-name

This is only one way to do it. The only constraint is that wrapdocker is used to start the Docker daemon within the build container.

like image 25
calebds Avatar answered Oct 19 '22 09:10

calebds


The answer is outdated, please check @Brad's solution below, use this as reference only

In your mycompany/buildimage

Install docker client

curl https://get.docker.io/builds/Linux/x86_64/docker-latest -o /usr/local/bin/docker
chmod +x /usr/local/bin/docker 

Then you can run docker build command use docker host environment

$ docker -H unix:///var/run/docker.sock build .

To make it easy and transparent, usually DOCKER_HOST environment can be set.

$ export DOCKER_HOST="unix:///var/run/docker.sock"
$ docker build .

Not familar with the drone installation, but this is the way docker provides

like image 1
Larry Cai Avatar answered Oct 19 '22 09:10

Larry Cai