1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Tina4 Ruby — production Docker image. Generated by `tina4 deploy docker`.
# Two-stage: compile gems in a builder that HAS a toolchain, then copy the
# resolved bundle into a slim runtime.
#
# The builder is the full `ruby:3.3` image, not `-slim`: several gems in the
# default dependency set ship native extensions (date, json, nio4r, sqlite3),
# and `-slim` carries no compiler, so `bundle install` dies with
# "Gem::Ext::BuildError: Failed to build gem native extension".
# The tina4 CLI is installed in EVERY Tina4 image and is the launcher: one
# `tina4 serve --production` across all four languages instead of four
# different per-language entry points. It is a single static musl binary
# copied from a published image -- a layer copy, no toolchain, no compile,
# no network fetch at build time. Override with
# --build-arg TINA4_CLI_IMAGE=... to pin or test a different CLI.
ARG =ghcr.io/tina4stack/tina4-cli:v3.8.63
FROM ${TINA4_CLI_IMAGE} AS tina4cli
FROM ruby:3.3 AS deps
WORKDIR /app
COPY Gemfile Gemfile.lock* ./
# `deployment true` is deliberately NOT set. It demands a lockfile that matches
# the image's bundler exactly, so a Gemfile.lock generated by a newer bundler on
# the developer's machine hard-fails the build. Installing without it lets
# bundler resolve, and self-upgrade, as needed.
RUN bundle config set --local without \
&& bundle config set --local path \
&& bundle install --jobs 4 \
&& rm -rf /app/vendor/bundle/rubycache
# puma at BUILD time, same reason as uvicorn in the Python image: otherwise
# `tina4 serve --production` shells out to `gem install puma` on every boot.
RUN
FROM ruby:3.3-slim
WORKDIR /app
COPY --from=tina4cli /usr/local/bin/tina4 /usr/local/bin/tina4
# Runtime shared libraries only. The extensions were compiled in the builder but
# still dynamically link against libsqlite3.
RUN apt-get update \
&& apt-get install -y --no-install-recommends libsqlite3-0 \
&& rm -rf /var/lib/apt/lists/*
ENV =true \
=false \
=vendor/bundle \
=development:test
COPY --from=deps /app/vendor /app/vendor
COPY --from=deps /usr/local/bundle /usr/local/bundle
COPY . /app
EXPOSE 7147
# One launcher for all four languages. --host defaults to 0.0.0.0, which is
# required: a server bound to 127.0.0.1 inside a container is unreachable
# through `docker run -p`. --no-browser because there is no browser here.
CMD [, , , ]