Browse code

Add new consolidated mkimage scripts

These new scripts are streamlined such that, for example, "contrib/mkimage/debootstrap" is _only_ responsible for filling a directory with the results of running debootstrap, and it can accept any arbitrary arguments.

Docker-DCO-1.1-Signed-off-by: Andrew Page <admwiggin@gmail.com> (github: tianon)

Tianon Gravi authored on 2014/05/02 06:38:44
Showing 5 changed files
1 1
new file mode 100755
... ...
@@ -0,0 +1,105 @@
0
+#!/usr/bin/env bash
1
+set -e
2
+
3
+mkimg="$(basename "$0")"
4
+
5
+usage() {
6
+	echo >&2 "usage: $mkimg [-d dir] [-t tag] script [script-args]"
7
+	echo >&2 "   ie: $mkimg -t someuser/debian debootstrap --variant=minbase jessie"
8
+	echo >&2 "       $mkimg -t someuser/ubuntu debootstrap --include=ubuntu-minimal trusty"
9
+	echo >&2 "       $mkimg -t someuser/busybox busybox-static"
10
+	echo >&2 "       $mkimg -t someuser/centos:5 rinse --distribution centos-5"
11
+	exit 1
12
+}
13
+
14
+scriptDir="$(dirname "$(readlink -f "$BASH_SOURCE")")/mkimage"
15
+
16
+optTemp=$(getopt --options '+d:t:h' --longoptions 'dir:,tag:,help' --name "$mkimg" -- "$@")
17
+eval set -- "$optTemp"
18
+unset optTemp
19
+
20
+dir=
21
+tag=
22
+while true; do
23
+	case "$1" in
24
+		-d|--dir) dir="$2" ; shift 2 ;;
25
+		-t|--tag) tag="$2" ; shift 2 ;;
26
+		-h|--help) usage ;;
27
+		--) shift ; break ;;
28
+	esac
29
+done
30
+
31
+script="$1"
32
+[ "$script" ] || usage
33
+shift
34
+
35
+if [ ! -x "$scriptDir/$script" ]; then
36
+	echo >&2 "error: $script does not exist or is not executable"
37
+	echo >&2 "  see $scriptDir for possible scripts"
38
+	exit 1
39
+fi
40
+
41
+# don't mistake common scripts like .febootstrap-minimize as image-creators
42
+if [[ "$script" == .* ]]; then
43
+	echo >&2 "error: $script is a script helper, not a script"
44
+	echo >&2 "  see $scriptDir for possible scripts"
45
+	exit 1
46
+fi
47
+
48
+delDir=
49
+if [ -z "$dir" ]; then
50
+	dir="$(mktemp -d ${TMPDIR:-/tmp}/docker-mkimage.XXXXXXXXXX)"
51
+	delDir=1
52
+fi
53
+
54
+rootfsDir="$dir/rootfs"
55
+( set -x; mkdir -p "$rootfsDir" )
56
+
57
+# pass all remaining arguments to $script
58
+"$scriptDir/$script" "$rootfsDir" "$@"
59
+
60
+# Docker mounts tmpfs at /dev and procfs at /proc so we can remove them
61
+rm -rf "$rootfsDir/dev" "$rootfsDir/proc"
62
+mkdir -p "$rootfsDir/dev" "$rootfsDir/proc"
63
+
64
+# make sure /etc/resolv.conf has something useful in it
65
+mkdir -p "$rootfsDir/etc"
66
+cat > "$rootfsDir/etc/resolv.conf" <<'EOF'
67
+nameserver 8.8.8.8
68
+nameserver 8.8.4.4
69
+EOF
70
+
71
+tarFile="$dir/rootfs.tar.xz"
72
+touch "$tarFile"
73
+
74
+(
75
+	set -x
76
+	tar --numeric-owner -caf "$tarFile" -C "$rootfsDir" --transform='s,^./,,' .
77
+)
78
+
79
+echo >&2 "+ cat > '$dir/Dockerfile'"
80
+cat > "$dir/Dockerfile" <<'EOF'
81
+FROM scratch
82
+ADD rootfs.tar.xz /
83
+EOF
84
+
85
+# if our generated image has a decent shell, let's set a default command
86
+for shell in /bin/bash /usr/bin/fish /usr/bin/zsh /bin/sh; do
87
+	if [ -x "$rootfsDir/$shell" ]; then
88
+		( set -x; echo 'CMD ["'"$shell"'"]' >> "$dir/Dockerfile" )
89
+		break
90
+	fi
91
+done
92
+
93
+( set -x; rm -rf "$rootfsDir" )
94
+
95
+if [ "$tag" ]; then
96
+	( set -x; docker build -t "$tag" "$dir" )
97
+elif [ "$delDir" ]; then
98
+	# if we didn't specify a tag and we're going to delete our dir, let's just build an untagged image so that we did _something_
99
+	( set -x; docker build "$dir" )
100
+fi
101
+
102
+if [ "$delDir" ]; then
103
+	( set -x; rm -rf "$dir" )
104
+fi
0 105
new file mode 100755
... ...
@@ -0,0 +1,28 @@
0
+#!/usr/bin/env bash
1
+set -e
2
+
3
+rootfsDir="$1"
4
+shift
5
+
6
+(
7
+	cd "$rootfsDir"
8
+
9
+	# effectively: febootstrap-minimize --keep-zoneinfo --keep-rpmdb --keep-services "$target"
10
+	#  locales
11
+	rm -rf usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}
12
+	#  docs
13
+	rm -rf usr/share/{man,doc,info,gnome/help}
14
+	#  cracklib
15
+	#rm -rf usr/share/cracklib
16
+	#  i18n
17
+	rm -rf usr/share/i18n
18
+	#  yum cache
19
+	rm -rf var/cache/yum
20
+	mkdir -p --mode=0755 var/cache/yum
21
+	#  sln
22
+	rm -rf sbin/sln
23
+	#  ldconfig
24
+	#rm -rf sbin/ldconfig
25
+	rm -rf etc/ld.so.cache var/cache/ldconfig
26
+	mkdir -p --mode=0755 var/cache/ldconfig
27
+)
0 28
new file mode 100755
... ...
@@ -0,0 +1,34 @@
0
+#!/usr/bin/env bash
1
+set -e
2
+
3
+rootfsDir="$1"
4
+shift
5
+
6
+busybox="$(which busybox 2>/dev/null || true)"
7
+if [ -z "$busybox" ]; then
8
+	echo >&2 'error: busybox: not found'
9
+	echo >&2 '  install it with your distribution "busybox-static" package'
10
+	exit 1
11
+fi
12
+if ! ldd "$busybox" 2>&1 | grep -q 'not a dynamic executable'; then
13
+	echo >&2 "error: '$busybox' appears to be a dynamic executable"
14
+	echo >&2 '  you should install your distribution "busybox-static" package instead'
15
+	exit 1
16
+fi
17
+
18
+mkdir -p "$rootfsDir/bin"
19
+rm -f "$rootfsDir/bin/busybox" # just in case
20
+cp "$busybox" "$rootfsDir/bin/busybox"
21
+
22
+(
23
+	cd "$rootfsDir"
24
+
25
+	IFS=$'\n'
26
+	modules=( $(bin/busybox --list-modules) )
27
+	unset IFS
28
+
29
+	for module in "${modules[@]}"; do
30
+		mkdir -p "$(dirname "$module")"
31
+		ln -sf /bin/busybox "$module"
32
+	done
33
+)
0 34
new file mode 100755
... ...
@@ -0,0 +1,125 @@
0
+#!/usr/bin/env bash
1
+set -e
2
+
3
+rootfsDir="$1"
4
+shift
5
+
6
+# we have to do a little fancy footwork to make sure "rootfsDir" becomes the second non-option argument to debootstrap
7
+
8
+before=()
9
+while [ $# -gt 0 ] && [[ "$1" == -* ]]; do
10
+	before+=( "$1" )
11
+	shift
12
+done
13
+
14
+suite="$1"
15
+shift
16
+
17
+(
18
+	set -x
19
+	debootstrap "${before[@]}" "$suite" "$rootfsDir" "$@"
20
+)
21
+
22
+# now for some Docker-specific tweaks
23
+
24
+# prevent init scripts from running during install/update
25
+echo >&2 "+ cat > '$rootfsDir/usr/sbin/policy-rc.d'"
26
+cat > "$rootfsDir/usr/sbin/policy-rc.d" <<'EOF'
27
+#!/bin/sh
28
+exit 101
29
+EOF
30
+chmod +x "$rootfsDir/usr/sbin/policy-rc.d"
31
+
32
+# prevent upstart scripts from running during install/update
33
+(
34
+	set -x
35
+	chroot "$rootfsDir" dpkg-divert --local --rename --add /sbin/initctl
36
+	ln -sf /bin/true "$rootfsDir/sbin/initctl"
37
+)
38
+
39
+# shrink the image, since apt makes us fat (wheezy: ~157.5MB vs ~120MB)
40
+( set -x; chroot "$rootfsDir" apt-get clean )
41
+
42
+# Ubuntu 10.04 sucks... :)
43
+if strings "$rootfsDir/usr/bin/dpkg" | grep -q unsafe-io; then
44
+	# force dpkg not to call sync() after package extraction (speeding up installs)
45
+	echo >&2 "+ echo force-unsafe-io > '$rootfsDir/etc/dpkg/dpkg.cfg.d/docker-apt-speedup'"
46
+	echo 'force-unsafe-io' > "$rootfsDir/etc/dpkg/dpkg.cfg.d/docker-apt-speedup"
47
+fi
48
+
49
+if [ -d /etc/apt/apt.conf.d ]; then
50
+	# _keep_ us lean by effectively running "apt-get clean" after every install
51
+	aptGetClean='"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true";'
52
+	echo >&2 "+ cat > '$rootfsDir/etc/apt/apt.conf.d/docker-clean'"
53
+	cat > "$rootfsDir/etc/apt/apt.conf.d/docker-clean" <<-EOF
54
+		DPkg::Post-Invoke { ${aptGetClean} };
55
+		APT::Update::Post-Invoke { ${aptGetClean} };
56
+
57
+		Dir::Cache::pkgcache "";
58
+		Dir::Cache::srcpkgcache "";
59
+	EOF
60
+
61
+	# remove apt-cache translations for fast "apt-get update"
62
+	echo >&2 "+ cat > '$rootfsDir/etc/apt/apt.conf.d/docker-no-languages'"
63
+	echo 'Acquire::Languages "none";' > "$rootfsDir/etc/apt/apt.conf.d/docker-no-languages"
64
+fi
65
+
66
+if [ -z "$DONT_TOUCH_SOURCES_LIST" ]; then
67
+	# tweak sources.list, where appropriate
68
+	lsbDist=
69
+	if [ -z "$lsbDist" -a -r "$rootfsDir/etc/os-release" ]; then
70
+		lsbDist="$(. "$rootfsDir/etc/os-release" && echo "$ID")"
71
+	fi
72
+	if [ -z "$lsbDist" -a -r "$rootfsDir/etc/lsb-release" ]; then
73
+		lsbDist="$(. "$rootfsDir/etc/lsb-release" && echo "$DISTRIB_ID")"
74
+	fi
75
+	if [ -z "$lsbDist" -a -r "$rootfsDir/etc/debian_version" ]; then
76
+		lsbDist='Debian'
77
+	fi
78
+	case "$lsbDist" in
79
+		debian|Debian)
80
+			# updates and security!
81
+			if [ "$suite" != 'sid' -a "$suite" != 'unstable' ]; then
82
+				(
83
+					set -x
84
+					sed -i "p; s/ $suite main$/ ${suite}-updates main/" "$rootfsDir/etc/apt/sources.list"
85
+					echo "deb http://security.debian.org $suite/updates main" >> "$rootfsDir/etc/apt/sources.list"
86
+				)
87
+			fi
88
+			;;
89
+		ubuntu|Ubuntu)
90
+			# add the universe, updates, and security repositories
91
+			(
92
+				set -x
93
+				sed -i "
94
+					s/ $suite main$/ $suite main universe/; p;
95
+					s/ $suite main/ ${suite}-updates main/; p;
96
+					s/ $suite-updates main/ ${suite}-security main/
97
+				" "$rootfsDir/etc/apt/sources.list"
98
+			)
99
+			;;
100
+		tanglu|Tanglu)
101
+			# add the updates repository
102
+			if [ "$suite" != 'devel' ]; then
103
+				(
104
+					set -x
105
+					sed -i "p; s/ $suite main$/ ${suite}-updates main/" "$rootfsDir/etc/apt/sources.list"
106
+				)
107
+			fi
108
+			;;
109
+		steamos|SteamOS)
110
+			# add contrib and non-free
111
+			(
112
+				set -x
113
+				sed -i "s/ $suite main$/ $suite main contrib non-free/" "$rootfsDir/etc/apt/sources.list"
114
+			)
115
+			;;
116
+	esac
117
+fi
118
+
119
+# make sure we're fully up-to-date, too
120
+(
121
+	set -x
122
+	chroot "$rootfsDir" apt-get update
123
+	chroot "$rootfsDir" apt-get dist-upgrade -y
124
+)
0 125
new file mode 100755
... ...
@@ -0,0 +1,25 @@
0
+#!/usr/bin/env bash
1
+set -e
2
+
3
+rootfsDir="$1"
4
+shift
5
+
6
+# specifying --arch below is safe because "$@" can override it and the "latest" one wins :)
7
+
8
+(
9
+	set -x
10
+	rinse --directory "$rootfsDir" --arch amd64 "$@"
11
+)
12
+
13
+"$(dirname "$BASH_SOURCE")/.febootstrap-minimize" "$rootfsDir"
14
+
15
+if [ -d "$rootfsDir/etc/sysconfig" ]; then
16
+	# allow networking init scripts inside the container to work without extra steps
17
+	echo 'NETWORKING=yes' > "$rootfsDir/etc/sysconfig/network"
18
+fi
19
+
20
+# make sure we're fully up-to-date, too
21
+(
22
+	set -x
23
+	chroot "$rootfsDir" yum update -y
24
+)