OILS / deps / images.sh View on Github | oils.pub

317 lines, 133 significant
1#!/usr/bin/env bash
2#
3# Manage container images for Soil
4#
5# Usage:
6# deps/images.sh <function name>
7#
8# Example: Rebuild an image:
9#
10# (1) Update LATEST_TAG
11#
12# (2) Rebuild
13#
14# deps/images.sh build soil-common # populates apt cache. WHY DO I NEED THIS?
15# deps/images.sh build soil-debian-12
16# deps/images.sh build soil-pea T # reuse package cache from apt-get
17# deps/images.sh smoke soil-pea
18#
19# (3) Push image and common, including latest
20#
21# deps/images.sh push soil-cpp-small v-2024-06-08
22#
23# deps/images.sh push soil-common v-2024-06-08
24# sudo docker tag oilshell/soil-common:{v-2024-06-08,latest}
25# deps/images.sh push soil-common latest
26#
27# (4) Update live version in 'soil/host-shim.sh live-image-tag'
28#
29# Our images:
30#
31# https://hub.docker.com/u/oilshell
32#
33# deps/images.sh list-tagged
34#
35# Bootstrapping Wedges
36# --------------------
37#
38# deps/images.sh build wedge-bootstrap-debian-10 T
39# deps/images.sh push wedge-bootstrap-debian-10 v-2024-06-08
40#
41# Building wedges:
42#
43# deps/wedge.sh boxed-spec-bin
44
45set -o nounset
46set -o pipefail
47set -o errexit
48
49source deps/podman.sh
50
51DOCKER=${DOCKER:-docker}
52
53# Build with this tag
54readonly LATEST_TAG='v-2024-12-20'
55
56# BUGS in Docker.
57#
58# https://stackoverflow.com/questions/69173822/docker-build-uses-wrong-dockerfile-content-bug
59
60# NOTE: This also clears the exec.cachemount
61prune() {
62 sudo $DOCKER builder prune -f
63}
64
65# https://stackoverflow.com/questions/62834806/docker-buildkit-cache-location-size-and-id
66#
67# It lives somewhere in /var/lib/docker/overlay2
68
69show-cachemount() {
70 sudo $DOCKER system df -v --format '{{ .BuildCache | json }}' \
71 | jq '.[] | select(.CacheType == "exec.cachemount")' | tee _tmp/cachemount.txt
72
73 cat _tmp/cachemount.txt | jq -r '.ID' | while read id; do
74 sudo tree /var/lib/docker/overlay2/$id
75 sudo du --si -s /var/lib/docker/overlay2/$id
76 echo
77 done
78}
79
80tag-common() {
81 local hash=$1 # get hash from $0 list-tagged
82 sudo $DOCKER tag $hash oilshell/soil-common:latest
83}
84
85build() {
86 local name=${1:-soil-dummy}
87 local use_cache=${2:-} # OFF by default
88
89 # set -x
90 local -a flags
91 if test -n "$use_cache"; then
92 flags=()
93 else
94 flags=('--no-cache=true')
95 fi
96 #flags+=('--progress=plain')
97
98 # Uh BuildKit is not the default on Linux!
99 # http://jpetazzo.github.io/2021/11/30/docker-build-container-images-antipatterns/
100 #
101 # It is more parallel and has colored output.
102
103 # TODO: use --authfile and more
104 #export-podman
105
106 # can't preserve the entire env: https://github.com/containers/buildah/issues/3887
107 #sudo --preserve-env=CONTAINERS_REGISTRIES_CONF --preserve-env=REGISTRY_AUTH_FILE \
108 sudo -E DOCKER_BUILDKIT=1 \
109 $DOCKER build "${flags[@]}" \
110 --tag "oilshell/$name:$LATEST_TAG" \
111 --file deps/Dockerfile.$name .
112}
113
114list-images() {
115 for name in deps/Dockerfile.*; do
116 local image_id=${name//'deps/Dockerfile.'/}
117 if test "$image_id" = 'test-image'; then
118 continue
119 fi
120 echo $image_id
121 done
122}
123
124tag-all-latest() {
125 list-images | egrep -v 'wedge-builder|bootstrap' | while read image; do
126 local tag
127 tag=$(soil/host-shim.sh live-image-tag $image)
128
129 echo "$tag $image"
130
131 # syntax: source -> target
132 sudo $DOCKER tag oilshell/soil-$image:$tag oilshell/soil-$image:latest
133 done
134}
135
136push-all-latest() {
137 ### 'latest' can lag behind the tagged version, so push to catch up
138
139 # because our 'my-sizes' script fetches the latest manifest
140
141 list-images | grep -v 'wedge-builder|bootstrap' | while read image_id; do
142 echo "___ $image_id"
143 push $image_id latest
144 done
145}
146
147list-tagged() {
148 sudo $DOCKER images 'oilshell/*' #:v-*'
149}
150
151push() {
152 local name=${1:-soil-dummy}
153 local tag=${2:-$LATEST_TAG}
154
155 # TODO: replace with flags
156 #export-podman
157
158 local image="oilshell/$name:$tag"
159
160 # -E for export-podman vars
161 sudo -E $DOCKER push $image
162 #sudo -E $DOCKER --log-level=debug push $image
163}
164
165smoke-test-script() {
166 echo '
167for file in /etc/debian_version /etc/lsb-release; do
168 if test -f $file; then
169 # spec/ble-idioms tests this
170 #grep -E "foo|^10" $file; echo grep=$?
171
172 echo $file
173 echo
174 cat $file
175 echo
176 else
177 echo "($file does not exist)"
178 fi
179done
180
181echo "bash $BASH_VERSION"
182
183git --version
184
185for name in python python2 python3; do
186 if which $name; then
187 $name -V
188 else
189 echo "$name not found"
190 fi
191done
192
193echo PATH=$PATH
194
195curl https://ci.oilshell.org/
196'
197}
198
199smoke() {
200 sudo $0 _smoke "$@"
201}
202
203_smoke() {
204 ### Smoke test of container
205 local name=${1:-soil-dummy}
206 local tag=${2:-$LATEST_TAG}
207 local docker=${3:-$DOCKER}
208 local prefix=${4:-}
209
210 #sudo docker run oilshell/$name
211 #sudo docker run oilshell/$name python2 -c 'print("python2")'
212
213 # Need to point at registries.conf ?
214 #export-podman
215
216 $docker run ${prefix}oilshell/$name:$tag bash -c "$(smoke-test-script)"
217
218 # Python 2.7 build/prepare.sh requires this
219 #sudo docker run oilshell/$name python -V
220
221 #sudo docker run oilshell/$name python3 -c 'import pexpect; print(pexpect)'
222}
223
224smoke-podman() {
225 local name=${1:-dummy}
226
227 # 2025-04: I need to do 'podman login docker.io'
228 #
229 # Running without root
230
231 # need explicit docker.io prefix with podman
232 # smoke $name latest podman docker.io/
233
234 local tag='latest'
235 local prefix='docker.io/'
236 smoke-test-script | podman run -i ${prefix}oilshell/soil-$name:$tag bash
237}
238
239cmd() {
240 ### Run an arbitrary command
241 local name=${1:-soil-dummy}
242 local tag=${2:-$LATEST_TAG}
243
244 shift 2
245
246 sudo $DOCKER run oilshell/$name:$tag "$@"
247}
248
249utf8() {
250 # needed for a spec test, not the default on Debian
251 cmd ovm-tarball bash -c 'LC_ALL=en_US.UTF-8; echo $LC_ALL'
252}
253
254mount-test() {
255 local name=${1:-soil-dummy}
256
257 local -a argv
258 if test $# -le 1; then
259 argv=(sh -c 'ls -l /home/uke/oil')
260 else
261 argv=( "${@:2}" ) # index 2 not 1, weird shell behavior
262 fi
263
264 # mount Oil directory as /app
265 sudo $DOCKER run \
266 --mount "type=bind,source=$PWD,target=/home/uke/oil" \
267 oilshell/$name "${argv[@]}"
268}
269
270image-history() {
271 local image_id=${1:-soil-dummy}
272 local tag=${2:-latest}
273
274 local image="oilshell/$image_id"
275
276 sudo $DOCKER history $image:$tag
277}
278
279save() {
280 local image_id=${1:-soil-dummy}
281 local tag=${2:-latest}
282
283 local image="oilshell/$image_id"
284
285 mkdir -p _tmp/images
286 local out=_tmp/images/$image_id.tar
287
288 # Use > instead of -o so it doesn'th have root permissions
289 time sudo $DOCKER save $image:$tag > $out
290 ls -l -h $out
291}
292
293# This shows CREATED, command CREATED BY, size
294# It's a human readable size though
295#
296# This doesn't really have anything better
297# https://gist.github.com/MichaelSimons/fb588539dcefd9b5fdf45ba04c302db6
298#
299# It's annoying that the remote registry API is different than the local API.
300
301layers() {
302 local name=${1:-soil-dummy}
303 local tag=${2:-$LATEST_TAG}
304
305 local image="oilshell/$name:$tag"
306
307 # Gah this still prints 237M, not the exact number of bytes!
308 # --format ' {{ .Size }} '
309 sudo $DOCKER history --no-trunc $image
310
311 echo $'Size\tVirtual Size'
312 sudo $DOCKER inspect $image \
313 | jq --raw-output '.[0] | [.Size, .VirtualSize] | @tsv' \
314 | commas
315}
316
317"$@"