Slide 73 of 74

Containers

Writing it, and running what it wrote
$ hive container main.hive
Wrote Dockerfile for main.hive (0s)
$ docker build -t main .
$ docker run --rm -p 8080:8080 main

# A Dockerfile already there is left alone, and ours is named for itself.
$ hive container main.hive
Wrote Dockerfile-hive-container for main.hive (0s)
$ docker build -f Dockerfile-hive-container -t main .
What it writes
# syntax=docker/dockerfile:1
#
# Builds and runs main.hive, from nothing but this folder.
#
#   docker build -t main .
#   docker run --rm -p 8080:8080 main

##############################################################################
# Stage 1 — download Go and the compiler, then build
##############################################################################
FROM debian:bookworm-slim AS builder

# What Docker is building for: amd64 on an ordinary machine, arm64 on an
# Apple-silicon one or a Graviton.
ARG TARGETARCH

# ... curl, then Go itself for that architecture ...

# The compiler itself — this one, rather than whatever release is newest on
# the day the image is built.
ARG HIVEC_VERSION=v0.2.10
RUN curl -fsSL \
      "https://github.com/R0DR160HM/hive-lang/releases/download/${HIVEC_VERSION}/hivec-linux-${TARGETARCH}" \
      -o /usr/local/bin/hivec \
 && chmod +x /usr/local/bin/hivec

# A static binary, so the runtime stage below needs no libc.
ENV CGO_ENABLED=0

WORKDIR /app
COPY . .

RUN hivec build /app/main.hive \
 && test -x /app/main

##############################################################################
# Stage 2 — runtime
##############################################################################
FROM gcr.io/distroless/static-debian12 AS runtime
WORKDIR /app
COPY --from=builder /app/main /usr/local/bin/main

# 8080 is where this program serves: hive.net.httpServe(8080, ...) says so.
EXPOSE 8080

ENTRYPOINT ["/usr/local/bin/main"]

hive container main.hive writes a Dockerfile for the program into the folder the command was run in, which is also the build's context. It checks the program first, as hive check would, so a program that does not compile gets its errors rather than an image build that fails ten minutes later.

Nothing has to be installed to build the image but Docker:

  • The first stage downloads Go, and the compiler that wrote the file, for the platform being built for: amd64 on an ordinary machine and arm64 on an Apple-silicon one, so the build is native either way. The compiler is pinned in ARG HIVEC_VERSION, so an image never follows a newer release on its own, and docker build --build-arg HIVEC_VERSION=v9.9.9 . builds with another one.
  • The second stage is the executable alone, on distroless/static: no Go, no compiler, not even a shell — only the certificates an HTTPS call needs and the time zones.

What is not a template is read off the program. A hive.net.httpServe(8080, ...) becomes an EXPOSE 8080, with a comment saying where the number came from, and a program that serves nothing exposes nothing. An import that names a repository puts git in the build stage, and a program that opens a database runs go mod tidy before anything compiles. Everything beside the Dockerfile goes into the build, so a .dockerignore is what narrows it.

What comes out is an ordinary Dockerfile, and editing it is expected. A Dockerfile already in the folder is never written over: ours is called Dockerfile-hive-container instead, the command says which it wrote, and building from it takes docker build -f Dockerfile-hive-container .. This tour is served out of an image built this way.