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

418 lines, 162 significant
1#!/usr/bin/env bash
2#
3# Manage container images for Soil
4#
5# Usage:
6# deps/images.sh <function name>
7#
8# Dirs maybe to clear:
9#
10# $0 clean-all # Start from scratch
11#
12# Example:
13#
14# (1) Update LATEST_TAG
15#
16# (2) Bootstrapping Wedges
17#
18# $0 build wedge-bootstrap-debian-12 # runs init-deb-cache
19#
20# (3) Building wedges:
21#
22# build/deps.sh fetch
23# build/deps.sh boxed-wedges
24# build/deps.sh boxed-spec-bin
25#
26# (4) Rebuild an image
27#
28# $0 build soil-debian-12 # runs init-deb-cache and populate the cache
29# $0 build soil-test-image T # reuse package cache from apt-get
30# $0 smoke soil-test-image # smoke test
31#
32# (5) Update live version in 'soil/host-shim.sh live-image-tag'
33#
34# (6) Push Everything you Built
35#
36# $0 push wedge-bootstrap-debian-12 # pushes both $LATEST_TAG and latest
37# $0 push soil-debian-12 # ditto
38# $0 push soil-test-image # ditto
39#
40# More
41# ----
42#
43# Images: https://hub.docker.com/u/oilshell
44#
45# $0 list-tagged # Show versions of images
46#
47# $0 show-cachemount # show files in apt cache
48#
49# $0 prune # seems to clear the cache
50
51set -o nounset
52set -o pipefail
53set -o errexit
54
55source deps/podman.sh
56
57DOCKER=${DOCKER:-docker}
58
59readonly LATEST_TAG='v-2025-05-01' # add libreadline-dev to wedge-bootstrap-debian-12
60
61clean-all() {
62 dirs='_build/wedge/tmp _build/wedge/binary _build/deps-source'
63 #rm -r -f $dirs
64 sudo rm -r -f $dirs
65}
66
67list-images() {
68 for name in deps/Dockerfile.*; do
69 local image_id=${name//'deps/Dockerfile.'/}
70 if test "$image_id" = 'test-image'; then
71 continue
72 fi
73 echo $image_id
74 done
75}
76
77list-tagged() {
78 sudo $DOCKER images 'oilshell/*' #:v-*'
79}
80
81_latest-one() {
82 local name=$1
83 $DOCKER images "oilshell/$name" | head -n 3
84}
85
86_list-latest() {
87 # Should rebuild all these
88 # Except I also want to change the Dockerfile to use Debian 12
89 list-images | xargs -n 1 -- $0 _latest-one
90}
91
92list-latest() {
93 sudo $0 _list-latest
94}
95
96# BUGS in Docker.
97#
98# https://stackoverflow.com/questions/69173822/docker-build-uses-wrong-dockerfile-content-bug
99
100# NOTE: This also clears the exec.cachemount
101prune() {
102 sudo $DOCKER builder prune -f
103}
104
105# https://stackoverflow.com/questions/62834806/docker-buildkit-cache-location-size-and-id
106#
107# It lives somewhere in /var/lib/docker/overlay2
108
109show-cachemount() {
110 sudo $DOCKER system df -v --format '{{ .BuildCache | json }}' \
111 | jq '.[] | select(.CacheType == "exec.cachemount")' | tee _tmp/cachemount.txt
112
113 cat _tmp/cachemount.txt | jq -r '.ID' | while read id; do
114 sudo tree /var/lib/docker/overlay2/$id
115 sudo du --si -s /var/lib/docker/overlay2/$id
116 echo
117 done
118}
119
120tag-latest() {
121 local name=${1:-wedge-bootstrap-debian-12}
122 local tag_built_with=${2:-$LATEST_TAG}
123
124 set -x # 'docker tag' is annoyingly silent
125 sudo $DOCKER tag oilshell/$name:{$tag_built_with,latest}
126}
127
128build() {
129 local name=${1:-soil-dummy}
130
131 # OFF by default. TODO: use_cache setting should be automatic
132 local use_cache=${2:-}
133
134 # set -x
135 local -a flags
136 if test -n "$use_cache"; then
137 flags=()
138 else
139 flags=('--no-cache=true')
140 fi
141 #flags+=('--progress=plain')
142
143 # Uh BuildKit is not the default on Linux!
144 # http://jpetazzo.github.io/2021/11/30/docker-build-container-images-antipatterns/
145 #
146 # It is more parallel and has colored output.
147
148 # TODO: use --authfile and more
149 #export-podman
150
151 # can't preserve the entire env: https://github.com/containers/buildah/issues/3887
152 #sudo --preserve-env=CONTAINERS_REGISTRIES_CONF --preserve-env=REGISTRY_AUTH_FILE \
153 sudo -E DOCKER_BUILDKIT=1 \
154 $DOCKER build "${flags[@]}" \
155 --tag "oilshell/$name:$LATEST_TAG" \
156 --file deps/Dockerfile.$name .
157
158 # Avoid hassle by also tagging it
159 tag-latest $name
160}
161
162build-many() {
163 echo 'TODO: use_cache should be automatic - all but 2 images use it'
164}
165
166build-all() {
167 # Should rebuild all these
168 # Except I also want to change the Dockerfile to use Debian 12
169 list-images | egrep -v 'test-image|ovm-tarball|benchmarks|wedge-bootstrap|debian-12'
170}
171
172push() {
173 local name=${1:-soil-dummy}
174 local tag=${2:-$LATEST_TAG}
175
176 # TODO: replace with flags
177 #export-podman
178
179 local image="oilshell/$name:$tag"
180
181 set -x
182
183 # -E for export-podman vars
184 sudo -E $DOCKER push $image
185 #sudo -E $DOCKER --log-level=debug push $image
186
187 # Also push the 'latest' tag, to avoid getting out of sync
188 sudo -E $DOCKER push oilshell/$name:latest
189}
190
191push-many() {
192 for name in "$@"; do
193 push $name
194 done
195}
196
197smoke-test-script() {
198 echo '
199for file in /etc/debian_version /etc/lsb-release; do
200 if test -f $file; then
201 # spec/ble-idioms tests this
202 #grep -E "foo|^10" $file; echo grep=$?
203
204 echo $file
205 echo
206 cat $file
207 echo
208 else
209 echo "($file does not exist)"
210 fi
211done
212
213echo "bash $BASH_VERSION"
214
215git --version
216
217for name in python python2 python3; do
218 if which $name; then
219 $name -V
220 else
221 echo "$name not found"
222 fi
223done
224
225echo PATH=$PATH
226
227#curl https://op.oilshell.org/
228
229if true; then
230 python2 -c "import readline; print(readline)"
231 echo
232
233 python3 -c "import ssl; print(ssl)"
234 echo
235
236 find /usr/lib | grep -i readline
237 echo
238
239 ls /wedge/oils-for-unix.org/pkg/python2/
240 ls /wedge/oils-for-unix.org/pkg/python2/2.7.18/lib/python2.7/lib-dynload
241
242 ldd /wedge/oils-for-unix.org/pkg/python2/2.7.18/lib/python2.7/lib-dynload/readline.so
243 echo
244
245 exit
246
247 dpkg -S /usr/lib/x86_64-linux-gnu/libssl.so.3
248 echo
249
250 #ls -l /usr/lib/x86_64-linux-gnu/libssl.so.1.1
251
252 apt-cache show libssl-dev
253
254 # find /lib | grep -i libssl
255 # echo
256 # find /usr/local | grep -i libssl
257 # echo
258 # python3-config --libs
259
260 # Useful command
261 # ldconfig -v #| grep ssl
262 # echo
263
264 #find / -name 'libssl.so*'
265fi
266'
267}
268
269smoke() {
270 sudo $0 _smoke "$@"
271}
272
273_smoke() {
274 ### Smoke test of container
275 local name=${1:-soil-dummy}
276 local tag=${2:-$LATEST_TAG}
277 local docker=${3:-$DOCKER}
278 local prefix=${4:-}
279
280 #sudo docker run oilshell/$name
281 #sudo docker run oilshell/$name python2 -c 'print("python2")'
282
283 # Need to point at registries.conf ?
284 #export-podman
285
286 $docker run ${prefix}oilshell/$name:$tag bash -c "$(smoke-test-script)"
287
288 # Python 2.7 build/prepare.sh requires this
289 #sudo docker run oilshell/$name python -V
290
291 #sudo docker run oilshell/$name python3 -c 'import pexpect; print(pexpect)'
292}
293
294smoke-podman() {
295 local name=${1:-dummy}
296
297 # 2025-04: I need to do 'podman login docker.io'
298 #
299 # Running without root
300
301 # need explicit docker.io prefix with podman
302 # smoke $name latest podman docker.io/
303
304 local tag='latest'
305 local prefix='docker.io/'
306 smoke-test-script | podman run -i ${prefix}oilshell/soil-$name:$tag bash
307}
308
309cmd() {
310 ### Run an arbitrary command
311 local name=${1:-soil-dummy}
312 local tag=${2:-$LATEST_TAG}
313
314 shift 2
315
316 sudo $DOCKER run oilshell/$name:$tag "$@"
317}
318
319utf8() {
320 # needed for a spec test, not the default on Debian
321 cmd ovm-tarball bash -c 'LC_ALL=en_US.UTF-8; echo $LC_ALL'
322}
323
324mount-test() {
325 local name=${1:-soil-dummy}
326
327 local -a argv
328 if test $# -le 1; then
329 argv=(sh -c 'ls -l /home/uke/oil')
330 else
331 argv=( "${@:2}" ) # index 2 not 1, weird shell behavior
332 fi
333
334 # mount Oil directory as /app
335 sudo $DOCKER run \
336 --mount "type=bind,source=$PWD,target=/home/uke/oil" \
337 oilshell/$name "${argv[@]}"
338}
339
340image-history() {
341 local image_id=${1:-soil-dummy}
342 local tag=${2:-latest}
343
344 local image="oilshell/$image_id"
345
346 sudo $DOCKER history $image:$tag
347}
348
349save() {
350 local image_id=${1:-soil-dummy}
351 local tag=${2:-latest}
352
353 local image="oilshell/$image_id"
354
355 mkdir -p _tmp/images
356 local out=_tmp/images/$image_id.tar
357
358 # Use > instead of -o so it doesn'th have root permissions
359 time sudo $DOCKER save $image:$tag > $out
360 ls -l -h $out
361}
362
363# This shows CREATED, command CREATED BY, size
364# It's a human readable size though
365#
366# This doesn't really have anything better
367# https://gist.github.com/MichaelSimons/fb588539dcefd9b5fdf45ba04c302db6
368#
369# It's annoying that the remote registry API is different than the local API.
370
371layers() {
372 local name=${1:-soil-dummy}
373 local tag=${2:-$LATEST_TAG}
374
375 local image="oilshell/$name:$tag"
376
377 # Gah this still prints 237M, not the exact number of bytes!
378 # --format ' {{ .Size }} '
379 sudo $DOCKER history --no-trunc $image
380
381 echo $'Size\tVirtual Size'
382 sudo $DOCKER inspect $image \
383 | jq --raw-output '.[0] | [.Size, .VirtualSize] | @tsv' \
384 | commas
385}
386
387todo-debian-12() {
388 # 7 images
389 grep soil-common deps/Dockerfile.*
390}
391
392todo-purity() {
393 # TODO: we should pass --network none in $0 build
394 #
395 # Hm 7 images need pip download, should reduce them
396 #
397 # There are other sources of impurity, like:
398 # building the R-libs wedge
399 # soil-wild - we can't download the testdata, etc.
400
401 grep -l install-py3-libs deps/Dockerfile.*
402}
403
404todo-tree-shake() {
405 # We should invoke OSH to generate parts of the dockerfile? Or use podman
406 # probably?
407 #
408 # Or maybe it's a default layer in soil-debian-12?
409
410 grep task-five deps/Dockerfile.*
411}
412
413todo-relative() {
414 grep TODO # _build/wedge/relative, not _build/wedge/binary
415}
416
417"$@"
418