github.com/ssdev-go/moby@v17.12.1-ce-rc2+incompatible/contrib/mkimage/debootstrap (about) 1 #!/usr/bin/env bash 2 set -e 3 4 mkimgdeb="$(basename "$0")" 5 mkimg="$(dirname "$0").sh" 6 7 usage() { 8 echo >&2 "usage: $mkimgdeb rootfsDir suite [debootstrap-args]" 9 echo >&2 " note: $mkimgdeb meant to be used from $mkimg" 10 exit 1 11 } 12 13 rootfsDir="$1" 14 if [ -z "$rootfsDir" ]; then 15 echo >&2 "error: rootfsDir is missing" 16 echo >&2 17 usage 18 fi 19 shift 20 21 # we have to do a little fancy footwork to make sure "rootfsDir" becomes the second non-option argument to debootstrap 22 23 before=() 24 while [ $# -gt 0 ] && [[ "$1" == -* ]]; do 25 before+=( "$1" ) 26 shift 27 done 28 29 suite="$1" 30 if [ -z "$suite" ]; then 31 echo >&2 "error: suite is missing" 32 echo >&2 33 usage 34 fi 35 shift 36 37 # get path to "chroot" in our current PATH 38 chrootPath="$(type -P chroot || :)" 39 if [ -z "$chrootPath" ]; then 40 echo >&2 "error: chroot not found. Are you root?" 41 echo >&2 42 usage 43 fi 44 45 rootfs_chroot() { 46 # "chroot" doesn't set PATH, so we need to set it explicitly to something our new debootstrap chroot can use appropriately! 47 48 # set PATH and chroot away! 49 PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' \ 50 "$chrootPath" "$rootfsDir" "$@" 51 } 52 53 # allow for DEBOOTSTRAP=qemu-debootstrap ./mkimage.sh ... 54 : ${DEBOOTSTRAP:=debootstrap} 55 56 ( 57 set -x 58 $DEBOOTSTRAP "${before[@]}" "$suite" "$rootfsDir" "$@" 59 ) 60 61 # now for some Docker-specific tweaks 62 63 # prevent init scripts from running during install/update 64 echo >&2 "+ echo exit 101 > '$rootfsDir/usr/sbin/policy-rc.d'" 65 cat > "$rootfsDir/usr/sbin/policy-rc.d" <<-'EOF' 66 #!/bin/sh 67 68 # For most Docker users, "apt-get install" only happens during "docker build", 69 # where starting services doesn't work and often fails in humorous ways. This 70 # prevents those failures by stopping the services from attempting to start. 71 72 exit 101 73 EOF 74 chmod +x "$rootfsDir/usr/sbin/policy-rc.d" 75 76 # prevent upstart scripts from running during install/update 77 ( 78 set -x 79 rootfs_chroot dpkg-divert --local --rename --add /sbin/initctl 80 cp -a "$rootfsDir/usr/sbin/policy-rc.d" "$rootfsDir/sbin/initctl" 81 sed -i 's/^exit.*/exit 0/' "$rootfsDir/sbin/initctl" 82 ) 83 84 # shrink a little, since apt makes us cache-fat (wheezy: ~157.5MB vs ~120MB) 85 ( set -x; rootfs_chroot apt-get clean ) 86 87 # this file is one APT creates to make sure we don't "autoremove" our currently 88 # in-use kernel, which doesn't really apply to debootstraps/Docker images that 89 # don't even have kernels installed 90 rm -f "$rootfsDir/etc/apt/apt.conf.d/01autoremove-kernels" 91 92 # Ubuntu 10.04 sucks... :) 93 if strings "$rootfsDir/usr/bin/dpkg" | grep -q unsafe-io; then 94 # force dpkg not to call sync() after package extraction (speeding up installs) 95 echo >&2 "+ echo force-unsafe-io > '$rootfsDir/etc/dpkg/dpkg.cfg.d/docker-apt-speedup'" 96 cat > "$rootfsDir/etc/dpkg/dpkg.cfg.d/docker-apt-speedup" <<-'EOF' 97 # For most Docker users, package installs happen during "docker build", which 98 # doesn't survive power loss and gets restarted clean afterwards anyhow, so 99 # this minor tweak gives us a nice speedup (much nicer on spinning disks, 100 # obviously). 101 102 force-unsafe-io 103 EOF 104 fi 105 106 if [ -d "$rootfsDir/etc/apt/apt.conf.d" ]; then 107 # _keep_ us lean by effectively running "apt-get clean" after every install 108 aptGetClean='"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true";' 109 echo >&2 "+ cat > '$rootfsDir/etc/apt/apt.conf.d/docker-clean'" 110 cat > "$rootfsDir/etc/apt/apt.conf.d/docker-clean" <<-EOF 111 # Since for most Docker users, package installs happen in "docker build" steps, 112 # they essentially become individual layers due to the way Docker handles 113 # layering, especially using CoW filesystems. What this means for us is that 114 # the caches that APT keeps end up just wasting space in those layers, making 115 # our layers unnecessarily large (especially since we'll normally never use 116 # these caches again and will instead just "docker build" again and make a brand 117 # new image). 118 119 # Ideally, these would just be invoking "apt-get clean", but in our testing, 120 # that ended up being cyclic and we got stuck on APT's lock, so we get this fun 121 # creation that's essentially just "apt-get clean". 122 DPkg::Post-Invoke { ${aptGetClean} }; 123 APT::Update::Post-Invoke { ${aptGetClean} }; 124 125 Dir::Cache::pkgcache ""; 126 Dir::Cache::srcpkgcache ""; 127 128 # Note that we do realize this isn't the ideal way to do this, and are always 129 # open to better suggestions (https://github.com/docker/docker/issues). 130 EOF 131 132 # remove apt-cache translations for fast "apt-get update" 133 echo >&2 "+ echo Acquire::Languages 'none' > '$rootfsDir/etc/apt/apt.conf.d/docker-no-languages'" 134 cat > "$rootfsDir/etc/apt/apt.conf.d/docker-no-languages" <<-'EOF' 135 # In Docker, we don't often need the "Translations" files, so we're just wasting 136 # time and space by downloading them, and this inhibits that. For users that do 137 # need them, it's a simple matter to delete this file and "apt-get update". :) 138 139 Acquire::Languages "none"; 140 EOF 141 142 echo >&2 "+ echo Acquire::GzipIndexes 'true' > '$rootfsDir/etc/apt/apt.conf.d/docker-gzip-indexes'" 143 cat > "$rootfsDir/etc/apt/apt.conf.d/docker-gzip-indexes" <<-'EOF' 144 # Since Docker users using "RUN apt-get update && apt-get install -y ..." in 145 # their Dockerfiles don't go delete the lists files afterwards, we want them to 146 # be as small as possible on-disk, so we explicitly request "gz" versions and 147 # tell Apt to keep them gzipped on-disk. 148 149 # For comparison, an "apt-get update" layer without this on a pristine 150 # "debian:wheezy" base image was "29.88 MB", where with this it was only 151 # "8.273 MB". 152 153 Acquire::GzipIndexes "true"; 154 Acquire::CompressionTypes::Order:: "gz"; 155 EOF 156 157 # update "autoremove" configuration to be aggressive about removing suggests deps that weren't manually installed 158 echo >&2 "+ echo Apt::AutoRemove::SuggestsImportant 'false' > '$rootfsDir/etc/apt/apt.conf.d/docker-autoremove-suggests'" 159 cat > "$rootfsDir/etc/apt/apt.conf.d/docker-autoremove-suggests" <<-'EOF' 160 # Since Docker users are looking for the smallest possible final images, the 161 # following emerges as a very common pattern: 162 163 # RUN apt-get update \ 164 # && apt-get install -y <packages> \ 165 # && <do some compilation work> \ 166 # && apt-get purge -y --auto-remove <packages> 167 168 # By default, APT will actually _keep_ packages installed via Recommends or 169 # Depends if another package Suggests them, even and including if the package 170 # that originally caused them to be installed is removed. Setting this to 171 # "false" ensures that APT is appropriately aggressive about removing the 172 # packages it added. 173 174 # https://aptitude.alioth.debian.org/doc/en/ch02s05s05.html#configApt-AutoRemove-SuggestsImportant 175 Apt::AutoRemove::SuggestsImportant "false"; 176 EOF 177 fi 178 179 if [ -z "$DONT_TOUCH_SOURCES_LIST" ]; then 180 # tweak sources.list, where appropriate 181 lsbDist= 182 if [ -z "$lsbDist" -a -r "$rootfsDir/etc/os-release" ]; then 183 lsbDist="$(. "$rootfsDir/etc/os-release" && echo "$ID")" 184 fi 185 if [ -z "$lsbDist" -a -r "$rootfsDir/etc/lsb-release" ]; then 186 lsbDist="$(. "$rootfsDir/etc/lsb-release" && echo "$DISTRIB_ID")" 187 fi 188 if [ -z "$lsbDist" -a -r "$rootfsDir/etc/debian_version" ]; then 189 lsbDist='Debian' 190 fi 191 # normalize to lowercase for easier matching 192 lsbDist="$(echo "$lsbDist" | tr '[:upper:]' '[:lower:]')" 193 case "$lsbDist" in 194 debian) 195 # updates and security! 196 if curl -o /dev/null -s --head --fail "http://security.debian.org/dists/$suite/updates/main/binary-$(rootfs_chroot dpkg --print-architecture)/Packages.gz"; then 197 ( 198 set -x 199 sed -i " 200 p; 201 s/ $suite / ${suite}-updates / 202 " "$rootfsDir/etc/apt/sources.list" 203 echo "deb http://security.debian.org $suite/updates main" >> "$rootfsDir/etc/apt/sources.list" 204 ) 205 fi 206 ;; 207 ubuntu) 208 # add the updates and security repositories 209 ( 210 set -x 211 sed -i " 212 p; 213 s/ $suite / ${suite}-updates /; p; 214 s/ $suite-updates / ${suite}-security / 215 " "$rootfsDir/etc/apt/sources.list" 216 ) 217 ;; 218 tanglu) 219 # add the updates repository 220 if [ "$suite" != 'devel' ]; then 221 ( 222 set -x 223 sed -i " 224 p; 225 s/ $suite / ${suite}-updates / 226 " "$rootfsDir/etc/apt/sources.list" 227 ) 228 fi 229 ;; 230 steamos) 231 # add contrib and non-free if "main" is the only component 232 ( 233 set -x 234 sed -i "s/ $suite main$/ $suite main contrib non-free/" "$rootfsDir/etc/apt/sources.list" 235 ) 236 ;; 237 esac 238 fi 239 240 ( 241 set -x 242 243 # make sure we're fully up-to-date 244 rootfs_chroot sh -xc 'apt-get update && apt-get dist-upgrade -y' 245 246 # delete all the apt list files since they're big and get stale quickly 247 rm -rf "$rootfsDir/var/lib/apt/lists"/* 248 # this forces "apt-get update" in dependent images, which is also good 249 250 mkdir "$rootfsDir/var/lib/apt/lists/partial" # Lucid... "E: Lists directory /var/lib/apt/lists/partial is missing." 251 )