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.
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.
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:
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With