github.com/demonoid81/moby@v0.0.0-20200517203328-62dd8e17c460/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 ( 86 set -x 87 rootfs_chroot apt-get clean 88 ) 89 90 # this file is one APT creates to make sure we don't "autoremove" our currently 91 # in-use kernel, which doesn't really apply to debootstraps/Docker images that 92 # don't even have kernels installed 93 rm -f "$rootfsDir/etc/apt/apt.conf.d/01autoremove-kernels" 94 95 # Ubuntu 10.04 sucks... :) 96 if strings "$rootfsDir/usr/bin/dpkg" | grep -q unsafe-io; then 97 # force dpkg not to call sync() after package extraction (speeding up installs) 98 echo >&2 "+ echo force-unsafe-io > '$rootfsDir/etc/dpkg/dpkg.cfg.d/docker-apt-speedup'" 99 cat > "$rootfsDir/etc/dpkg/dpkg.cfg.d/docker-apt-speedup" <<- 'EOF' 100 # For most Docker users, package installs happen during "docker build", which 101 # doesn't survive power loss and gets restarted clean afterwards anyhow, so 102 # this minor tweak gives us a nice speedup (much nicer on spinning disks, 103 # obviously). 104 105 force-unsafe-io 106 EOF 107 fi 108 109 if [ -d "$rootfsDir/etc/apt/apt.conf.d" ]; then 110 # _keep_ us lean by effectively running "apt-get clean" after every install 111 aptGetClean='"rm -f /var/cache/apt/archives/*.deb /var/cache/apt/archives/partial/*.deb /var/cache/apt/*.bin || true";' 112 echo >&2 "+ cat > '$rootfsDir/etc/apt/apt.conf.d/docker-clean'" 113 cat > "$rootfsDir/etc/apt/apt.conf.d/docker-clean" <<- EOF 114 # Since for most Docker users, package installs happen in "docker build" steps, 115 # they essentially become individual layers due to the way Docker handles 116 # layering, especially using CoW filesystems. What this means for us is that 117 # the caches that APT keeps end up just wasting space in those layers, making 118 # our layers unnecessarily large (especially since we'll normally never use 119 # these caches again and will instead just "docker build" again and make a brand 120 # new image). 121 122 # Ideally, these would just be invoking "apt-get clean", but in our testing, 123 # that ended up being cyclic and we got stuck on APT's lock, so we get this fun 124 # creation that's essentially just "apt-get clean". 125 DPkg::Post-Invoke { ${aptGetClean} }; 126 APT::Update::Post-Invoke { ${aptGetClean} }; 127 128 Dir::Cache::pkgcache ""; 129 Dir::Cache::srcpkgcache ""; 130 131 # Note that we do realize this isn't the ideal way to do this, and are always 132 # open to better suggestions (https://github.com/demonoid81/moby/issues). 133 EOF 134 135 # remove apt-cache translations for fast "apt-get update" 136 echo >&2 "+ echo Acquire::Languages 'none' > '$rootfsDir/etc/apt/apt.conf.d/docker-no-languages'" 137 cat > "$rootfsDir/etc/apt/apt.conf.d/docker-no-languages" <<- 'EOF' 138 # In Docker, we don't often need the "Translations" files, so we're just wasting 139 # time and space by downloading them, and this inhibits that. For users that do 140 # need them, it's a simple matter to delete this file and "apt-get update". :) 141 142 Acquire::Languages "none"; 143 EOF 144 145 echo >&2 "+ echo Acquire::GzipIndexes 'true' > '$rootfsDir/etc/apt/apt.conf.d/docker-gzip-indexes'" 146 cat > "$rootfsDir/etc/apt/apt.conf.d/docker-gzip-indexes" <<- 'EOF' 147 # Since Docker users using "RUN apt-get update && apt-get install -y ..." in 148 # their Dockerfiles don't go delete the lists files afterwards, we want them to 149 # be as small as possible on-disk, so we explicitly request "gz" versions and 150 # tell Apt to keep them gzipped on-disk. 151 152 # For comparison, an "apt-get update" layer without this on a pristine 153 # "debian:wheezy" base image was "29.88 MB", where with this it was only 154 # "8.273 MB". 155 156 Acquire::GzipIndexes "true"; 157 Acquire::CompressionTypes::Order:: "gz"; 158 EOF 159 160 # update "autoremove" configuration to be aggressive about removing suggests deps that weren't manually installed 161 echo >&2 "+ echo Apt::AutoRemove::SuggestsImportant 'false' > '$rootfsDir/etc/apt/apt.conf.d/docker-autoremove-suggests'" 162 cat > "$rootfsDir/etc/apt/apt.conf.d/docker-autoremove-suggests" <<- 'EOF' 163 # Since Docker users are looking for the smallest possible final images, the 164 # following emerges as a very common pattern: 165 166 # RUN apt-get update \ 167 # && apt-get install -y <packages> \ 168 # && <do some compilation work> \ 169 # && apt-get purge -y --auto-remove <packages> 170 171 # By default, APT will actually _keep_ packages installed via Recommends or 172 # Depends if another package Suggests them, even and including if the package 173 # that originally caused them to be installed is removed. Setting this to 174 # "false" ensures that APT is appropriately aggressive about removing the 175 # packages it added. 176 177 # https://aptitude.alioth.debian.org/doc/en/ch02s05s05.html#configApt-AutoRemove-SuggestsImportant 178 Apt::AutoRemove::SuggestsImportant "false"; 179 EOF 180 fi 181 182 if [ -z "$DONT_TOUCH_SOURCES_LIST" ]; then 183 # tweak sources.list, where appropriate 184 lsbDist= 185 if [ -z "$lsbDist" -a -r "$rootfsDir/etc/os-release" ]; then 186 lsbDist="$(. "$rootfsDir/etc/os-release" && echo "$ID")" 187 fi 188 if [ -z "$lsbDist" -a -r "$rootfsDir/etc/lsb-release" ]; then 189 lsbDist="$(. "$rootfsDir/etc/lsb-release" && echo "$DISTRIB_ID")" 190 fi 191 if [ -z "$lsbDist" -a -r "$rootfsDir/etc/debian_version" ]; then 192 lsbDist='Debian' 193 fi 194 # normalize to lowercase for easier matching 195 lsbDist="$(echo "$lsbDist" | tr '[:upper:]' '[:lower:]')" 196 case "$lsbDist" in 197 debian) 198 # updates and security! 199 if curl -o /dev/null -s --head --location --fail "http://security.debian.org/dists/$suite/updates/main/binary-$(rootfs_chroot dpkg --print-architecture)/Packages.gz"; then 200 ( 201 set -x 202 sed -i " 203 p; 204 s/ $suite / ${suite}-updates / 205 " "$rootfsDir/etc/apt/sources.list" 206 echo "deb http://security.debian.org $suite/updates main" >> "$rootfsDir/etc/apt/sources.list" 207 ) 208 fi 209 ;; 210 ubuntu) 211 # add the updates and security repositories 212 ( 213 set -x 214 sed -i " 215 p; 216 s/ $suite / ${suite}-updates /; p; 217 s/ $suite-updates / ${suite}-security / 218 " "$rootfsDir/etc/apt/sources.list" 219 ) 220 ;; 221 tanglu) 222 # add the updates repository 223 if [ "$suite" != 'devel' ]; then 224 ( 225 set -x 226 sed -i " 227 p; 228 s/ $suite / ${suite}-updates / 229 " "$rootfsDir/etc/apt/sources.list" 230 ) 231 fi 232 ;; 233 steamos) 234 # add contrib and non-free if "main" is the only component 235 ( 236 set -x 237 sed -i "s/ $suite main$/ $suite main contrib non-free/" "$rootfsDir/etc/apt/sources.list" 238 ) 239 ;; 240 esac 241 fi 242 243 ( 244 set -x 245 246 # make sure we're fully up-to-date 247 rootfs_chroot sh -xc 'apt-get update && apt-get dist-upgrade -y' 248 249 # delete all the apt list files since they're big and get stale quickly 250 rm -rf "$rootfsDir/var/lib/apt/lists"/* 251 # this forces "apt-get update" in dependent images, which is also good 252 253 mkdir "$rootfsDir/var/lib/apt/lists/partial" # Lucid... "E: Lists directory /var/lib/apt/lists/partial is missing." 254 )