*/Dockerfile.template: Replace ADD with COPY
[dockerfile.git] / build.sh
1 #!/bin/sh
2 #
3 # Copyright (C) 2013-2014 W. Trevor King <wking@tremily.us>
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are met:
7 #
8 # * Redistributions of source code must retain the above copyright notice, this
9 # list of conditions and the following disclaimer.
10 #
11 # * Redistributions in binary form must reproduce the above copyright notice,
12 # this list of conditions and the following disclaimer in the documentation
13 # and/or other materials provided with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 # POSSIBILITY OF SUCH DAMAGE.
26
27 AUTHOR="${AUTHOR:-W. Trevor King <wking@tremily.us>}"
28 NAMESPACE="${NAMESPACE:-wking}"
29 DATE="${DATE:-20140904}"
30 MIRROR="${MIRROR:-http://distfiles.gentoo.org/}"
31 ARCH_URL="${ARCH_URL:-${MIRROR}releases/amd64/autobuilds/${DATE}/}"
32 STAGE3="${STAGE3:-stage3-amd64-${DATE}.tar.bz2}"
33 STAGE3_CONTENTS="${STAGE3_CONTENTS:-${STAGE3}.CONTENTS}"
34 STAGE3_DIGESTS="${STAGE3_DIGESTS:-${STAGE3}.DIGESTS.asc}"
35 PORTAGE_URL="${PORTAGE_URL:-${MIRROR}snapshots/}"
36 PORTAGE="${PORTAGE:-portage-${DATE}.tar.xz}"
37 PORTAGE_SIG="${PORTAGE_SIG:-${PORTAGE}.gpgsig}"
38
39 DOCKER_IO=$(command -v docker.io)
40 DOCKER="${DOCKER:-${DOCKER_IO:-docker}}"
41 BUILD_OPTS="${BUILD_OPTS:-}"
42
43 REPOS="${REPOS:-
44         portage
45         gentoo-portage
46         gentoo-python
47         gentoo-utc
48         gentoo-en-us
49         gentoo-openrc
50         gentoo-syslog
51         gentoo-java
52         gentoo-layman
53         gentoo-node
54         buildbot
55         docker-registry
56         elasticsearch
57         hubot
58         irker
59         memcached
60         nginx
61         nginx-proxy
62         kibana
63         kibana-azure
64         ngircd
65         package-cache
66         postgresql
67         redis
68         salt-minion
69         stunnel
70         }"
71
72 die()
73 {
74         echo "$1"
75         exit 1
76 }
77
78 msg()
79 {
80         echo "$@"
81 }
82
83 REALPATH="${REALPATH:-$(command -v realpath)}"
84 if [ -z "${REALPATH}" ]; then
85         READLINK="${READLINK:-$(command -v readlink)}"
86         if [ -n "${READLINK}" ]; then
87                 REALPATH="${READLINK} -f"
88         else
89                 die "need realpath or readlink to canonicalize paths"
90         fi
91 fi
92
93 # Does "${NAMESPACE}/${REPO}:${DATE}" exist?
94 # Returns 0 (exists) or 1 (missing).
95 #
96 # Arguments:
97 #
98 # 1: REPO
99 repo_exists()
100 {
101         REPO="${1}"
102         IMAGES=$("${DOCKER}" images "${NAMESPACE}/${REPO}")
103         MATCHES=$(echo "${IMAGES}" | grep "${DATE}")
104         if [ -z "${MATCHES}" ]; then
105                 return 1
106         fi
107         return 0
108 }
109
110 # If they don't already exist:
111 #
112 # * download the stage3 and
113 # * create "${NAMESPACE}/gentoo:${DATE}"
114 #
115 # Forcibly tag "${NAMESPACE}/gentoo:${DATE}" with "latest"
116 import_stage3()
117 {
118         msg "import stage3"
119         if ! repo_exists gentoo; then
120                 # import stage3 image from Gentoo mirrors
121
122                 for FILE in "${STAGE3}" "${STAGE3_CONTENTS}" "${STAGE3_DIGESTS}"; do
123                         if [ ! -f "downloads/${FILE}" ]; then
124                                 wget -O "downloads/${FILE}" "${ARCH_URL}${FILE}" ||
125                                         die "failed to download ${ARCH_URL}${FILE}"
126                         fi
127                 done
128
129                 gpg --verify "downloads/${STAGE3_DIGESTS}" ||
130                         die "insecure digests for gentoo"
131                 SHA512_HASHES=$(grep -A1 SHA512 "downloads/${STAGE3_DIGESTS}" | grep -v '^--')
132                 SHA512_CHECK=$(cd downloads/ && (echo "${SHA512_HASHES}" | sha512sum -c))
133                 SHA512_FAILED=$(echo "${SHA512_CHECK}" | grep FAILED)
134                 if [ -n "${SHA512_FAILED}" ]; then
135                         die "${SHA512_FAILED}"
136                 fi
137
138                 msg "import ${NAMESPACE}/gentoo:${DATE}"
139                 "${DOCKER}" import - "${NAMESPACE}/gentoo:${DATE}" < "downloads/${STAGE3}" ||
140                         die "failed to import gentoo"
141         fi
142
143         msg "tag ${NAMESPACE}/gentoo:latest"
144         "${DOCKER}" tag -f "${NAMESPACE}/gentoo:${DATE}" "${NAMESPACE}/gentoo:latest" ||
145                         die "failed to tag gentoo"
146 }
147
148 # If they don't already exist:
149 #
150 # * download a portage snapshot and
151 # * create "${NAMESPACE}/portage-import:${DATE}"
152 #
153 # Forcibly tag "${NAMESPACE}/portage-import:${DATE}" with "latest"
154 import_portage()
155 {
156         msg "import portage"
157         if ! repo_exists portage-import; then
158                 # import portage image from Gentoo mirrors
159
160                 for FILE in "${PORTAGE}" "${PORTAGE_SIG}"; do
161                         if [ ! -f "downloads/${FILE}" ]; then
162                                 wget -O "downloads/${FILE}" "${PORTAGE_URL}${FILE}" ||
163                                         die "failed to download ${PORTAGE_URL}${FILE}"
164                         fi
165                 done
166
167                 gpg --verify "downloads/${PORTAGE_SIG}" "downloads/${PORTAGE}" ||
168                         die "insecure digests for portage-import"
169
170                 msg "import ${NAMESPACE}/portage-import:${DATE}"
171                 "${DOCKER}" import - "${NAMESPACE}/portage-import:${DATE}" < "downloads/${PORTAGE}" ||
172                         die "failed to import portage-import"
173         fi
174
175         msg "tag ${NAMESPACE}/portage-import:latest"
176         "${DOCKER}" tag -f "${NAMESPACE}/portage-import:${DATE}" "${NAMESPACE}/portage-import:latest" ||
177                 die "failed to tag portage-import"
178 }
179
180 # extract Busybox for the portage image
181 #
182 # Arguments:
183 #
184 # 1: SUBDIR target subdirectory for the busybox binary
185 extract_busybox()
186 {
187         SUBDIR="${1}"
188         msg "extract Busybox binary to ${SUBDIR}"
189         THIS_DIR=$(dirname $($REALPATH $0))
190         CONTAINER="${NAMESPACE}-gentoo-${DATE}-extract-busybox"
191         "${DOCKER}" run --name "${CONTAINER}" -v "${THIS_DIR}/${SUBDIR}/":/tmp "${NAMESPACE}/gentoo:${DATE}" cp /bin/busybox /tmp/
192         "${DOCKER}" rm "${CONTAINER}"
193 }
194
195 # If it doesn't already exist:
196 #
197 # * create "${NAMESPACE}/${REPO}:${DATE}" from
198 #   "${REPO}/Dockerfile.template"
199 #
200 # Forcibly tag "${NAMESPACE}/${REPO}:${DATE}" with "latest"
201 #
202 # Arguments:
203 #
204 # 1: REPO
205 build_repo()
206 {
207         REPO="${1}"
208         msg "build repo ${REPO}"
209         if ! repo_exists "${REPO}"; then
210                 if [ "${REPO}" = portage ]; then
211                         extract_busybox "${REPO}"
212                 fi
213
214                 env -i \
215                         NAMESPACE="${NAMESPACE}" \
216                         TAG="${DATE}" \
217                         MAINTAINER="${AUTHOR}" \
218                         envsubst '
219                                 ${NAMESPACE}
220                                 ${TAG}
221                                 ${MAINTAINER}
222                                 ' \
223                                 < "${REPO}/Dockerfile.template" > "${REPO}/Dockerfile"
224
225                 msg "build ${NAMESPACE}/${REPO}:${DATE}"
226                 "${DOCKER}" build ${BUILD_OPTS} -t "${NAMESPACE}/${REPO}:${DATE}" "${REPO}" ||
227                         die "failed to build ${REPO}"
228         fi
229         msg "tag ${NAMESPACE}/${REPO}:latest"
230         "${DOCKER}" tag -f "${NAMESPACE}/${REPO}:${DATE}" "${NAMESPACE}/${REPO}:latest" ||
231                         die "failed to tag ${REPO}"
232 }
233
234 build()
235 {
236         import_stage3
237         import_portage
238
239         for REPO in ${REPOS}; do
240                 build_repo "${REPO}"
241         done
242 }
243
244 missing()
245 {
246         for REPO in gentoo portage-import ${REPOS}; do
247                 if ! repo_exists "${REPO}"; then
248                         msg "${REPO}"
249                 fi
250         done
251 }
252
253 ACTION="${1:-build}"
254
255 case "${ACTION}" in
256 build) build ;;
257 missing) missing ;;
258 --help) msg "usage: ${0} [--help] {build|missing}" ;;
259 *) die "invalid action '${ACTION}'" ;;
260 esac