|
@@ -0,0 +1,104 @@
|
|
|
+#!/usr/bin/env python
|
|
|
+
|
|
|
+# docker-build is a script to build docker images from source.
|
|
|
+# It will be deprecated once the 'build' feature is incorporated into docker itself.
|
|
|
+# (See https://github.com/dotcloud/docker/issues/278)
|
|
|
+#
|
|
|
+# Author: Solomon Hykes <solomon@dotcloud.com>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+# First create a valid Changefile, which defines a sequence of changes to apply to a base image.
|
|
|
+#
|
|
|
+# $ cat Changefile
|
|
|
+# # Start build from a know base image
|
|
|
+# from base:ubuntu-12.10
|
|
|
+# # Update ubuntu sources
|
|
|
+# run echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list
|
|
|
+# run apt-get update
|
|
|
+# # Install system packages
|
|
|
+# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
|
|
|
+# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl
|
|
|
+# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
|
|
|
+# # Insert files from the host (./myscript must be present in the current directory)
|
|
|
+# copy myscript /usr/local/bin/myscript
|
|
|
+#
|
|
|
+#
|
|
|
+# Run docker-build, and pass the contents of your Changefile as standard input.
|
|
|
+#
|
|
|
+# $ IMG=$(./docker-build < Changefile)
|
|
|
+#
|
|
|
+# This will take a while: for each line of the changefile, docker-build will:
|
|
|
+#
|
|
|
+# 1. Create a new container to execute the given command or insert the given file
|
|
|
+# 2. Wait for the container to complete execution
|
|
|
+# 3. Commit the resulting changes as a new image
|
|
|
+# 4. Use the resulting image as the input of the next step
|
|
|
+
|
|
|
+
|
|
|
+import sys
|
|
|
+import subprocess
|
|
|
+import json
|
|
|
+import hashlib
|
|
|
+
|
|
|
+def docker(args, stdin=None):
|
|
|
+ print "# docker " + " ".join(args)
|
|
|
+ p = subprocess.Popen(["docker"] + list(args), stdin=stdin, stdout=subprocess.PIPE)
|
|
|
+ return p.stdout
|
|
|
+
|
|
|
+def image_exists(img):
|
|
|
+ return docker(["inspect", img]).read().strip() != ""
|
|
|
+
|
|
|
+def run_and_commit(img_in, cmd, stdin=None):
|
|
|
+ run_id = docker(["run"] + (["-i", "-a", "stdin"] if stdin else ["-d"]) + [img_in, "/bin/sh", "-c", cmd], stdin=stdin).read().rstrip()
|
|
|
+ print "---> Waiting for " + run_id
|
|
|
+ result=int(docker(["wait", run_id]).read().rstrip())
|
|
|
+ if result != 0:
|
|
|
+ print "!!! '{}' return non-zero exit code '{}'. Aborting.".format(cmd, result)
|
|
|
+ sys.exit(1)
|
|
|
+ return docker(["commit", run_id]).read().rstrip()
|
|
|
+
|
|
|
+def insert(base, src, dst):
|
|
|
+ print "COPY {} to {} in {}".format(src, dst, base)
|
|
|
+ if dst == "":
|
|
|
+ raise Exception("Missing destination path")
|
|
|
+ stdin = file(src)
|
|
|
+ stdin.seek(0)
|
|
|
+ return run_and_commit(base, "cat > {0}; chmod +x {0}".format(dst), stdin=stdin)
|
|
|
+
|
|
|
+
|
|
|
+def main():
|
|
|
+ base=""
|
|
|
+ steps = []
|
|
|
+ try:
|
|
|
+ for line in sys.stdin.readlines():
|
|
|
+ line = line.strip()
|
|
|
+ # Skip comments and empty lines
|
|
|
+ if line == "" or line[0] == "#":
|
|
|
+ continue
|
|
|
+ op, param = line.split(" ", 1)
|
|
|
+ if op == "from":
|
|
|
+ print "FROM " + param
|
|
|
+ base = param
|
|
|
+ steps.append(base)
|
|
|
+ elif op == "run":
|
|
|
+ print "RUN " + param
|
|
|
+ result = run_and_commit(base, param)
|
|
|
+ steps.append(result)
|
|
|
+ base = result
|
|
|
+ print "===> " + base
|
|
|
+ elif op == "copy":
|
|
|
+ src, dst = param.split(" ", 1)
|
|
|
+ result = insert(base, src, dst)
|
|
|
+ steps.append(result)
|
|
|
+ base = result
|
|
|
+ print "===> " + base
|
|
|
+ else:
|
|
|
+ print "Skipping uknown op " + op
|
|
|
+ except:
|
|
|
+ docker(["rmi"] + steps)
|
|
|
+ raise
|
|
|
+ print base
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main()
|