mirror of https://github.com/docker/docs.git
Added docker-build (formerly github.com/shykes/changer) as a contrib script
This commit is contained in:
parent
79d934bfb0
commit
048f9f4974
|
@ -0,0 +1,68 @@
|
||||||
|
# docker-build: build your software with docker
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
docker-builder requires:
|
||||||
|
|
||||||
|
1) A reasonably recent Python setup (tested on 2.7.2).
|
||||||
|
|
||||||
|
2) A running docker daemon at version 0.1.4 or more recent (http://www.docker.io/gettingstarted)
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
If all the steps succeed, the result will be an image containing the combined results of each build step.
|
||||||
|
You can trace back those build steps by inspecting the image's history:
|
||||||
|
|
||||||
|
$ docker history $IMG
|
||||||
|
ID CREATED CREATED BY
|
||||||
|
1e9e2045de86 A few seconds ago /bin/sh -c cat > /usr/local/bin/myscript; chmod +x /usr/local/bin/git
|
||||||
|
77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang
|
||||||
|
77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl
|
||||||
|
77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q git
|
||||||
|
83e85d155451 A few seconds ago /bin/sh -c apt-get update
|
||||||
|
bfd53b36d9d3 A few seconds ago /bin/sh -c echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list
|
||||||
|
base 2 weeks ago /bin/bash
|
||||||
|
27cf78414709 2 weeks ago
|
||||||
|
|
||||||
|
|
||||||
|
Note that your build started from 'base', as instructed by your Changefile. But that base image itself seems to have been built in 2 steps - hence the extra step in the history.
|
||||||
|
|
||||||
|
|
||||||
|
You can use this build technique to create any image you want: a database, a web application, or anything else that can be build by a sequence of unix commands - in other words, anything else.
|
||||||
|
|
|
@ -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()
|
|
@ -0,0 +1,11 @@
|
||||||
|
# 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
|
Loading…
Reference in New Issue