From 9dc9e0c940316161b218a532e704125246127d50 Mon Sep 17 00:00:00 2001 From: yackob03 Date: Thu, 24 Oct 2013 14:57:05 -0400 Subject: [PATCH] Add a docker-in-docker container that will run the build server. --- buildserver/Dockerfile | 27 +++++++++++++++++++++ buildserver/Readme.md | 14 ++++++++++- buildserver/buildserver.py | 35 +++++++++++++++------------ buildserver/startserver | 48 ++++++++++++++++++++++++++++++++++++++ buildserver/test.html | 2 +- 5 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 buildserver/Dockerfile create mode 100644 buildserver/startserver diff --git a/buildserver/Dockerfile b/buildserver/Dockerfile new file mode 100644 index 000000000..c58e9f0ad --- /dev/null +++ b/buildserver/Dockerfile @@ -0,0 +1,27 @@ +FROM lopter/raring-base +MAINTAINER jake@devtable.com + +RUN echo deb http://archive.ubuntu.com/ubuntu precise universe > /etc/apt/sources.list.d/universe.list +RUN apt-get update -qq +RUN apt-get install -qqy iptables ca-certificates lxc python-virtualenv git python-dev + +# This will use the latest public release. To use your own, comment it out... +ADD https://get.docker.io/builds/Linux/x86_64/docker-latest /usr/local/bin/docker +# ...then uncomment the following line, and copy your docker binary to current dir. +#ADD ./docker /usr/local/bin/docker + +# Install the files +ADD ./startserver /usr/local/bin/startserver +ADD ./buildserver.py ./buildserver.py +ADD ./test.html ./test.html +ADD ./requirements-nover.txt ./requirements-nover.txt + +RUN chmod +x /usr/local/bin/docker /usr/local/bin/startserver + +RUN virtualenv --distribute venv +RUN venv/bin/pip install -r requirements-nover.txt + +VOLUME /var/lib/docker + +EXPOSE 5002:5002 +CMD startserver \ No newline at end of file diff --git a/buildserver/Readme.md b/buildserver/Readme.md index 8cc88d12d..6b36df9ee 100644 --- a/buildserver/Readme.md +++ b/buildserver/Readme.md @@ -1 +1,13 @@ -This must be run on Python version 2.7.4 or later (Ubuntu 13.04) for security reasons. \ No newline at end of file +To build: + +``` +sudo docker build -t quay.io/quay/buildserver . +sudo docker push quay.io/quay/buildserver +``` + +To run: + +``` +sudo docker pull quay.io/quay/buildserver +sudo docker run -d -privileged -lxc-conf="aa_profile=unconfined" quay.io/quay/buildserver +``` \ No newline at end of file diff --git a/buildserver/buildserver.py b/buildserver/buildserver.py index 6ebdd5c9b..94bf2dbe2 100644 --- a/buildserver/buildserver.py +++ b/buildserver/buildserver.py @@ -54,16 +54,6 @@ def prepare_dockerfile(request_file): return build_dir -MIME_PROCESSORS = { - 'application/zip': prepare_zip, - 'text/plain': prepare_dockerfile, -} - - -builds = {} -pool = ThreadPool(1) - - def build_image(build_dir, tag_name, num_steps, result_object): try: logger.debug('Does this show up?') @@ -106,11 +96,8 @@ def build_image(build_dir, tag_name, num_steps, result_object): current_image = 0 image_progress = 0 for status in resp: - logger.debug(status) - if u'status' in status: status_msg = status[u'status'] - next_image = r'(Pushing|Image) [a-z0-9]+( already pushed, skipping)?$' match = re.match(next_image, status_msg) if match: @@ -141,7 +128,18 @@ def build_image(build_dir, tag_name, num_steps, result_object): result_object['message'] = e.message -@app.route('/build', methods=['POST']) +MIME_PROCESSORS = { + 'application/zip': prepare_zip, + 'text/plain': prepare_dockerfile, + 'application/octet-stream': prepare_dockerfile, +} + + +builds = {} +pool = ThreadPool(1) + + +@app.route('/build/', methods=['POST']) def start_build(): docker_input = request.files['dockerfile'] c_type = docker_input.content_type @@ -180,7 +178,7 @@ def start_build(): return redirect(url_for('get_status', job_id=job_id)) -@app.route('/status/') +@app.route('/build/') def get_status(job_id): if job_id not in builds: abort(400) @@ -188,6 +186,13 @@ def get_status(job_id): return jsonify(builds[job_id]) +@app.route('/build/', methods=['GET']) +def get_all_status(): + return jsonify({ + 'builds': builds, + }) + + if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT) app.run(host='0.0.0.0', port=5002, debug=True) \ No newline at end of file diff --git a/buildserver/startserver b/buildserver/startserver new file mode 100644 index 000000000..4947a618a --- /dev/null +++ b/buildserver/startserver @@ -0,0 +1,48 @@ +#!/bin/bash + +# First, make sure that cgroups are mounted correctly. +CGROUP=/sys/fs/cgroup + +[ -d $CGROUP ] || + mkdir $CGROUP + +mountpoint -q $CGROUP || + mount -n -t tmpfs -o uid=0,gid=0,mode=0755 cgroup $CGROUP || { + echo "Could not make a tmpfs mount. Did you use -privileged?" + exit 1 + } + +# Mount the cgroup hierarchies exactly as they are in the parent system. +for SUBSYS in $(cut -d: -f2 /proc/1/cgroup) +do + [ -d $CGROUP/$SUBSYS ] || mkdir $CGROUP/$SUBSYS + mountpoint -q $CGROUP/$SUBSYS || + mount -n -t cgroup -o $SUBSYS cgroup $CGROUP/$SUBSYS +done + +# Note: as I write those lines, the LXC userland tools cannot setup +# a "sub-container" properly if the "devices" cgroup is not in its +# own hierarchy. Let's detect this and issue a warning. +grep -q :devices: /proc/1/cgroup || + echo "WARNING: the 'devices' cgroup should be in its own hierarchy." +grep -qw devices /proc/1/cgroup || + echo "WARNING: it looks like the 'devices' cgroup is not mounted." + +# Now, close extraneous file descriptors. +pushd /proc/self/fd +for FD in * +do + case "$FD" in + # Keep stdin/stdout/stderr + [012]) + ;; + # Nuke everything else + *) + eval exec "$FD>&-" + ;; + esac +done +popd + +docker -d & +exec venv/bin/python buildserver.py 2> buildserver.log \ No newline at end of file diff --git a/buildserver/test.html b/buildserver/test.html index 0137b766b..9a08eb994 100644 --- a/buildserver/test.html +++ b/buildserver/test.html @@ -1,6 +1,6 @@ -
+