Fossil SCM
Commit [cda5d6a7] invalidated the BusyBox steps in the Tcl and Python examples in §3.2 of the containers doc.
Commit
ddcdc6f30bbc1e84c05b5e0e2f48e6363774b20fd9d5b8faa3009c15483fa7ef
Parent
0f9224e98a1d8c7…
1 file changed
+15
-18
+15
-18
| --- www/containers.md | ||
| +++ www/containers.md | ||
| @@ -231,11 +231,11 @@ | ||
| 231 | 231 | for the sake of discussion, we’ll say you’ve chosen [Method |
| 232 | 232 | 2](./alerts.md#db), which requires a Tcl interpreter and its SQLite |
| 233 | 233 | extension to push messages into the outbound email queue DB, presumably |
| 234 | 234 | bind-mounted into the container. |
| 235 | 235 | |
| 236 | -One way to do that is to replace STAGE 2 and 3 in the stock `Dockerfile` | |
| 236 | +You can do that by replacing STAGEs 2 and 3 in the stock `Dockerfile` | |
| 237 | 237 | with this: |
| 238 | 238 | |
| 239 | 239 | ``` |
| 240 | 240 | ## --------------------------------------------------------------------- |
| 241 | 241 | ## STAGE 2: Pare that back to the bare essentials, plus Tcl. |
| @@ -242,10 +242,11 @@ | ||
| 242 | 242 | ## --------------------------------------------------------------------- |
| 243 | 243 | FROM alpine AS run |
| 244 | 244 | ARG UID=499 |
| 245 | 245 | ENV PATH "/sbin:/usr/sbin:/bin:/usr/bin" |
| 246 | 246 | COPY --from=builder /tmp/fossil /bin/ |
| 247 | + COPY tools/email-sender.tcl /bin/ | |
| 247 | 248 | RUN set -x \ |
| 248 | 249 | && echo "fossil:x:${UID}:${UID}:User:/museum:/false" >> /etc/passwd \ |
| 249 | 250 | && echo "fossil:x:${UID}:fossil" >> /etc/group \ |
| 250 | 251 | && install -d -m 700 -o fossil -g fossil log museum \ |
| 251 | 252 | && apk add --no-cache tcl sqlite-tcl |
| @@ -258,29 +259,26 @@ | ||
| 258 | 259 | echo 'puts [info patchlevel]' | |
| 259 | 260 | docker exec -i $(make container-version) tclsh |
| 260 | 261 | 8.6.12 |
| 261 | 262 | ``` |
| 262 | 263 | |
| 263 | -You can remove the installation of `busybox-static` in STAGE 1 since | |
| 264 | -Alpine is already based on BusyBox.(^We can’t do “`FROM busybox`” since | |
| 265 | -we need `apk` in this new second stage. Although this means we end up | |
| 266 | -with back-to-back Alpine stages, it isn’t redundant; the second one | |
| 267 | -starts fresh, allowing us to copy in only what we absolutely need from | |
| 268 | -the first.) You should also remove the `PATH` override in the “RUN” | |
| 264 | +You should remove the `PATH` override in the “RUN” | |
| 269 | 265 | stage, since it’s written for the case where everything is in `/bin`. |
| 266 | +With these additions, we need the longer `PATH` shown above to have | |
| 267 | +ready access to them all. | |
| 270 | 268 | |
| 271 | 269 | Another useful case to consider is that you’ve installed a [server |
| 272 | 270 | extension](./serverext.wiki) and you need an interpreter for that |
| 273 | 271 | script. The first option above won’t work except in the unlikely case that |
| 274 | 272 | it’s written for one of the bare-bones script interpreters that BusyBox |
| 275 | 273 | ships.(^BusyBox’s `/bin/sh` is based on the old 4.4BSD Lite Almquist |
| 276 | 274 | shell, implementing little more than what POSIX specified in 1989, plus |
| 277 | -equally stripped-down versions of AWK and `sed`.) | |
| 275 | +equally stripped-down versions of `awk` and `sed`.) | |
| 278 | 276 | |
| 279 | 277 | Let’s say the extension is written in Python. While you could handle it |
| 280 | -the same way we do with the Tcl example above, because Python is more | |
| 281 | -popular, we have more options. Let’s inject a Python environment into | |
| 278 | +the same way we do with the Tcl example above, Python is more | |
| 279 | +popular, giving us more options. Let’s inject a Python environment into | |
| 282 | 280 | the stock Fossil container via a suitable “[distroless]” image instead: |
| 283 | 281 | |
| 284 | 282 | ``` |
| 285 | 283 | ## --------------------------------------------------------------------- |
| 286 | 284 | ## STAGE 2: Pare that back to the bare essentials, plus Python. |
| @@ -296,26 +294,25 @@ | ||
| 296 | 294 | && echo "fossil:x:${UID}:${UID}:User:/museum:/false" >> /etc/passwd \ |
| 297 | 295 | && echo "fossil:x:${UID}:fossil" >> /etc/group \ |
| 298 | 296 | && install -d -m 700 -o fossil -g fossil log museum |
| 299 | 297 | ``` |
| 300 | 298 | |
| 299 | +You will also have to add `busybox-static` to the APK package list in | |
| 300 | +STAGE 1 for the `RUN` script at the end of that stage to work, since the | |
| 301 | +[Chainguard Python image][cgimgs] lacks a shell, on purpose. The need to | |
| 302 | +install root-level binaries is why we change `USER` temporarily here. | |
| 303 | + | |
| 301 | 304 | Build it and test that it works like so: |
| 302 | 305 | |
| 303 | 306 | ``` |
| 304 | 307 | $ make container-run && |
| 305 | 308 | docker exec -i $(make container-version) python --version |
| 306 | 309 | 3.11.2 |
| 307 | 310 | ``` |
| 308 | 311 | |
| 309 | -Relative to the Tcl example, the change from “`alpine`” to [Chainguard’s | |
| 310 | -Python image][cgimgs] means we have no BusyBox environment to execute | |
| 311 | -the `RUN` command with, so we have to copy the `busybox.static` binary | |
| 312 | -in from STAGE 1 and install it in this new STAGE 2 for the same reason | |
| 313 | -the stock container does.(^This is the main reason we change `USER` | |
| 314 | -temporarily to `root` here.) There are a few other steps required to | |
| 315 | -avoid causing a conflict between our previously bare-bones “OS” layer | |
| 316 | -and what the Chainguard image provides. The compensation for this hassle | |
| 312 | +The compensation for the hassle of using Chainguard over something more | |
| 313 | +general purpose like Alpine + “`apk add python`” | |
| 317 | 314 | is huge: we no longer leave a package manager sitting around inside the |
| 318 | 315 | container, waiting for some malefactor to figure out how to abuse it. |
| 319 | 316 | |
| 320 | 317 | Beware that there’s a limit to this über-jail’s ability to save you when |
| 321 | 318 | you go and provide a more capable OS layer like this. The container |
| 322 | 319 |
| --- www/containers.md | |
| +++ www/containers.md | |
| @@ -231,11 +231,11 @@ | |
| 231 | for the sake of discussion, we’ll say you’ve chosen [Method |
| 232 | 2](./alerts.md#db), which requires a Tcl interpreter and its SQLite |
| 233 | extension to push messages into the outbound email queue DB, presumably |
| 234 | bind-mounted into the container. |
| 235 | |
| 236 | One way to do that is to replace STAGE 2 and 3 in the stock `Dockerfile` |
| 237 | with this: |
| 238 | |
| 239 | ``` |
| 240 | ## --------------------------------------------------------------------- |
| 241 | ## STAGE 2: Pare that back to the bare essentials, plus Tcl. |
| @@ -242,10 +242,11 @@ | |
| 242 | ## --------------------------------------------------------------------- |
| 243 | FROM alpine AS run |
| 244 | ARG UID=499 |
| 245 | ENV PATH "/sbin:/usr/sbin:/bin:/usr/bin" |
| 246 | COPY --from=builder /tmp/fossil /bin/ |
| 247 | RUN set -x \ |
| 248 | && echo "fossil:x:${UID}:${UID}:User:/museum:/false" >> /etc/passwd \ |
| 249 | && echo "fossil:x:${UID}:fossil" >> /etc/group \ |
| 250 | && install -d -m 700 -o fossil -g fossil log museum \ |
| 251 | && apk add --no-cache tcl sqlite-tcl |
| @@ -258,29 +259,26 @@ | |
| 258 | echo 'puts [info patchlevel]' | |
| 259 | docker exec -i $(make container-version) tclsh |
| 260 | 8.6.12 |
| 261 | ``` |
| 262 | |
| 263 | You can remove the installation of `busybox-static` in STAGE 1 since |
| 264 | Alpine is already based on BusyBox.(^We can’t do “`FROM busybox`” since |
| 265 | we need `apk` in this new second stage. Although this means we end up |
| 266 | with back-to-back Alpine stages, it isn’t redundant; the second one |
| 267 | starts fresh, allowing us to copy in only what we absolutely need from |
| 268 | the first.) You should also remove the `PATH` override in the “RUN” |
| 269 | stage, since it’s written for the case where everything is in `/bin`. |
| 270 | |
| 271 | Another useful case to consider is that you’ve installed a [server |
| 272 | extension](./serverext.wiki) and you need an interpreter for that |
| 273 | script. The first option above won’t work except in the unlikely case that |
| 274 | it’s written for one of the bare-bones script interpreters that BusyBox |
| 275 | ships.(^BusyBox’s `/bin/sh` is based on the old 4.4BSD Lite Almquist |
| 276 | shell, implementing little more than what POSIX specified in 1989, plus |
| 277 | equally stripped-down versions of AWK and `sed`.) |
| 278 | |
| 279 | Let’s say the extension is written in Python. While you could handle it |
| 280 | the same way we do with the Tcl example above, because Python is more |
| 281 | popular, we have more options. Let’s inject a Python environment into |
| 282 | the stock Fossil container via a suitable “[distroless]” image instead: |
| 283 | |
| 284 | ``` |
| 285 | ## --------------------------------------------------------------------- |
| 286 | ## STAGE 2: Pare that back to the bare essentials, plus Python. |
| @@ -296,26 +294,25 @@ | |
| 296 | && echo "fossil:x:${UID}:${UID}:User:/museum:/false" >> /etc/passwd \ |
| 297 | && echo "fossil:x:${UID}:fossil" >> /etc/group \ |
| 298 | && install -d -m 700 -o fossil -g fossil log museum |
| 299 | ``` |
| 300 | |
| 301 | Build it and test that it works like so: |
| 302 | |
| 303 | ``` |
| 304 | $ make container-run && |
| 305 | docker exec -i $(make container-version) python --version |
| 306 | 3.11.2 |
| 307 | ``` |
| 308 | |
| 309 | Relative to the Tcl example, the change from “`alpine`” to [Chainguard’s |
| 310 | Python image][cgimgs] means we have no BusyBox environment to execute |
| 311 | the `RUN` command with, so we have to copy the `busybox.static` binary |
| 312 | in from STAGE 1 and install it in this new STAGE 2 for the same reason |
| 313 | the stock container does.(^This is the main reason we change `USER` |
| 314 | temporarily to `root` here.) There are a few other steps required to |
| 315 | avoid causing a conflict between our previously bare-bones “OS” layer |
| 316 | and what the Chainguard image provides. The compensation for this hassle |
| 317 | is huge: we no longer leave a package manager sitting around inside the |
| 318 | container, waiting for some malefactor to figure out how to abuse it. |
| 319 | |
| 320 | Beware that there’s a limit to this über-jail’s ability to save you when |
| 321 | you go and provide a more capable OS layer like this. The container |
| 322 |
| --- www/containers.md | |
| +++ www/containers.md | |
| @@ -231,11 +231,11 @@ | |
| 231 | for the sake of discussion, we’ll say you’ve chosen [Method |
| 232 | 2](./alerts.md#db), which requires a Tcl interpreter and its SQLite |
| 233 | extension to push messages into the outbound email queue DB, presumably |
| 234 | bind-mounted into the container. |
| 235 | |
| 236 | You can do that by replacing STAGEs 2 and 3 in the stock `Dockerfile` |
| 237 | with this: |
| 238 | |
| 239 | ``` |
| 240 | ## --------------------------------------------------------------------- |
| 241 | ## STAGE 2: Pare that back to the bare essentials, plus Tcl. |
| @@ -242,10 +242,11 @@ | |
| 242 | ## --------------------------------------------------------------------- |
| 243 | FROM alpine AS run |
| 244 | ARG UID=499 |
| 245 | ENV PATH "/sbin:/usr/sbin:/bin:/usr/bin" |
| 246 | COPY --from=builder /tmp/fossil /bin/ |
| 247 | COPY tools/email-sender.tcl /bin/ |
| 248 | RUN set -x \ |
| 249 | && echo "fossil:x:${UID}:${UID}:User:/museum:/false" >> /etc/passwd \ |
| 250 | && echo "fossil:x:${UID}:fossil" >> /etc/group \ |
| 251 | && install -d -m 700 -o fossil -g fossil log museum \ |
| 252 | && apk add --no-cache tcl sqlite-tcl |
| @@ -258,29 +259,26 @@ | |
| 259 | echo 'puts [info patchlevel]' | |
| 260 | docker exec -i $(make container-version) tclsh |
| 261 | 8.6.12 |
| 262 | ``` |
| 263 | |
| 264 | You should remove the `PATH` override in the “RUN” |
| 265 | stage, since it’s written for the case where everything is in `/bin`. |
| 266 | With these additions, we need the longer `PATH` shown above to have |
| 267 | ready access to them all. |
| 268 | |
| 269 | Another useful case to consider is that you’ve installed a [server |
| 270 | extension](./serverext.wiki) and you need an interpreter for that |
| 271 | script. The first option above won’t work except in the unlikely case that |
| 272 | it’s written for one of the bare-bones script interpreters that BusyBox |
| 273 | ships.(^BusyBox’s `/bin/sh` is based on the old 4.4BSD Lite Almquist |
| 274 | shell, implementing little more than what POSIX specified in 1989, plus |
| 275 | equally stripped-down versions of `awk` and `sed`.) |
| 276 | |
| 277 | Let’s say the extension is written in Python. While you could handle it |
| 278 | the same way we do with the Tcl example above, Python is more |
| 279 | popular, giving us more options. Let’s inject a Python environment into |
| 280 | the stock Fossil container via a suitable “[distroless]” image instead: |
| 281 | |
| 282 | ``` |
| 283 | ## --------------------------------------------------------------------- |
| 284 | ## STAGE 2: Pare that back to the bare essentials, plus Python. |
| @@ -296,26 +294,25 @@ | |
| 294 | && echo "fossil:x:${UID}:${UID}:User:/museum:/false" >> /etc/passwd \ |
| 295 | && echo "fossil:x:${UID}:fossil" >> /etc/group \ |
| 296 | && install -d -m 700 -o fossil -g fossil log museum |
| 297 | ``` |
| 298 | |
| 299 | You will also have to add `busybox-static` to the APK package list in |
| 300 | STAGE 1 for the `RUN` script at the end of that stage to work, since the |
| 301 | [Chainguard Python image][cgimgs] lacks a shell, on purpose. The need to |
| 302 | install root-level binaries is why we change `USER` temporarily here. |
| 303 | |
| 304 | Build it and test that it works like so: |
| 305 | |
| 306 | ``` |
| 307 | $ make container-run && |
| 308 | docker exec -i $(make container-version) python --version |
| 309 | 3.11.2 |
| 310 | ``` |
| 311 | |
| 312 | The compensation for the hassle of using Chainguard over something more |
| 313 | general purpose like Alpine + “`apk add python`” |
| 314 | is huge: we no longer leave a package manager sitting around inside the |
| 315 | container, waiting for some malefactor to figure out how to abuse it. |
| 316 | |
| 317 | Beware that there’s a limit to this über-jail’s ability to save you when |
| 318 | you go and provide a more capable OS layer like this. The container |
| 319 |