Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ This changelog covers five gems, which release together on the same version:

* The installed `Dockerfile` sets `OMP_NUM_THREADS` and `OMP_THREAD_LIMIT`. OpenMP sizes its thread pool from the host's core count, and a container's `cpus` quota is a CFS quota rather than an affinity mask, so libvips and ImageMagick asked a 98-core host for 98 threads however small the cell's share of it was. A thread stack is 8MB of private anonymous memory, which `RLIMIT_DATA` charges, so the pool alone cleared the cell's `memory` limit — and libgomp calls `exit(1)` on the first `pthread_create` it cannot satisfy. Match `OMP_NUM_THREADS` to the container's `cpus`. An upgrade leaves an existing `Dockerfile` alone, so a cell installed before this needs both added by hand and the image rebuilt. `docs/DEPLOYMENT.md` covers why the guard has to be a test rather than a deploy to beta: the failure exists only at production's core count.

* The installed `Dockerfile` applies Debian's pending security patches with an `apt-get upgrade` after the `FROM`. `docker build --pull` takes the newest base tag, but the tag itself can sit behind an advisory that is already in `trixie-security` until [docker-library/ruby](https://github.com/docker-library/ruby) rebuilds it, so a clean build shipped a fixable High that no rebuild of the cell could clear. Upgrading during the build makes the image's patch level its own rather than upstream's release cadence, and it stops the class rather than the one advisory. An upgrade leaves an existing `Dockerfile` alone, so a cell installed before this needs the line added by hand and the image rebuilt.

### HotCell::Server

#### Fixed
Expand Down
7 changes: 7 additions & 0 deletions hotcell-client/lib/hot_cell/install/Dockerfile.tt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
ARG RUBY_VERSION=3.4
FROM ruby:${RUBY_VERSION}-slim

# Apply Debian's pending security patches. `--pull` takes the newest base tag, and the tag can still be
# behind an advisory that is already in `trixie-security`, because only a rebuild by docker-library/ruby
# moves it. Upgrading here makes the image's patch level its own rather than upstream's release cadence,
# and it is what keeps the image scan in CI passing on a fixable vulnerability the base has not picked up
# yet. It costs a layer and a little build time on every build.
RUN apt-get update && apt-get upgrade -y --no-install-recommends && rm -rf /var/lib/apt/lists/*

# Install the tools and libraries your operations run — and nothing else. For example:
#
# RUN apt-get update && \
Expand Down
14 changes: 14 additions & 0 deletions hotcell-client/test/install_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,20 @@ def test_install_bounds_the_openmp_thread_pools
end
end

# `--pull` takes the newest base tag, but that tag itself can sit behind a Debian advisory until
# docker-library/ruby rebuilds it, and the image scan gate blocks on a fixable High no rebuild of this
# repository can clear. Applying the pending security patches during the build makes the gate's claim the
# image's own rather than upstream's release cadence.
def test_install_applies_the_bases_pending_security_patches
Dir.mktmpdir do |root|
HotCell::Install.call(root, out: StringIO.new)

dockerfile = File.read(File.join(root, "hotcell", "Dockerfile"))

assert_match(/apt-get update && apt-get upgrade -y.*rm -rf \/var\/lib\/apt\/lists/, dockerfile)
end
end

def test_install_leaves_an_existing_file_exactly_as_it_is
Dir.mktmpdir do |root|
customized = File.join(root, "hotcell", "Dockerfile")
Expand Down